TypeScript 2.1介绍


本文整理自网络,侵删。

TypeScript 2.1介绍

keyof和Lookup类型

在JavaScript中,使用期望属性名称作为参数的API是相当普遍的,但到目前为止,还无法表达这些API中出现的类型关系。

输入索引类型查询或keyof;索引类型查询keyof T可以为T生成允许的属性名称类型。keyof T类型被认为是一种string的子类型。

示例

interface Person {
    name: string;
    age: number;
    location: string;
}

type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[];  // "length" | "push" | "pop" | "concat" | ...
type K3 = keyof { [x: string]: Person };  // string

其中的双重属性是索引访问类型,也称为lookup类型。从语法上讲,它们看起来完全像元素访问,但是写成类型:

示例

type P1 = Person["name"];  // string
type P2 = Person["name" | "age"];  // string | number
type P3 = string["charAt"];  // (pos: number) => string
type P4 = string[]["push"];  // (...items: string[]) => number
type P5 = string[][0];  // string

您可以将此模式与类型系统的其他部分一起使用,以获得类型安全的查找。

function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];  // Inferred type is T[K]
}

function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
    obj[key] = value;
}

let x = { foo: 10, bar: "hello!" };

let foo = getProperty(x, "foo"); // number
let bar = getProperty(x, "bar"); // string

let oops = getProperty(x, "wargarbl"); // Error! "wargarbl" is not "foo" | "bar"

setProperty(x, "foo", "string"); // Error!, string expected number

映射类型

一个常见的任务是采用现有类型并使其每个属性完全可选。假设我们有一个Person:

interface Person {
    name: string;
    age: number;
    location: string;
}

它的部分版本是:

interface PartialPerson {
    name?: string;
    age?: number;
    location?: string;
}

使用Mapped类型,PartialPerson可以写为Person类型的广义转换,例如:

type Partial<T> = {
    [P in keyof T]?: T[P];
};

type PartialPerson = Partial<Person>;

映射类型是通过获取文字类型的并集,并为新对象类型计算一组属性来生成的。它们与Python中的列表推导类似,但它们不是在列表中生成新元素,而是在类型中生成新属性。

除此了Partial之外,Mapped Types还可以在类型上表达许多有用的转换:

// Keep types the same, but make each property to be read-only.
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

// Same property names, but make the value a promise instead of a concrete one
type Deferred<T> = {
    [P in keyof T]: Promise<T[P]>;
};

// Wrap proxies around properties of T
type Proxify<T> = {
    [P in keyof T]: { get(): T[P]; set(v: T[P]): void }
};

Partial,Readonly,Record,和Pick

Partial和Readonly,如前所述,是非常有用的结构。您可以使用它们来描述一些常见的JS例程,例如:

function assign<T>(obj: T, props: Partial<T>): void;
function freeze<T>(obj: T): Readonly<T>;

因此,它们现在默认包含在标准库中。

我们还包括另外两种实用程序类型:Record和Pick。

// From T pick a set of properties K
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;

const nameAndAgeOnly = pick(person, "name", "age");  // { name: string, age: number }
// For every properties K of type T, transform it to U
function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>

const names = { foo: "hello", bar: "world", baz: "bye" };
const lengths = mapObject(names, s => s.length);  // { foo: number, bar: number, baz: number }

对象扩展与休息

TypeScript 2.1支持ESnext Spread和Rest。

与数组扩展类似,扩展对象可以很方便地获得浅层副本:

let copy = { ...original };

同样,您可以合并多个不同的对象。在以下示例中,merged将具有来自foo,bar和baz的属性。

let merged = { ...foo, ...bar, ...baz };

您还可以覆盖现有属性并添加新属性:

let obj = { x: 1, y: "string" };
var newObj = {...obj, z: 3, y: 4}; // { x: number, y: number, z: number }

指定扩展操作的顺序决定了生成的对象中最终的属性;以后的属性会在以前创建的属性上“win out”。

对象休息是对象扩展的双重对象,因为它们可以提取在解构元素时不会被拾取的任何额外属性:

let obj = { x: 1, y: 1, z: 1 };
let { z, ...obj1 } = obj;
obj1; // {x: number, y:number};

下层异步功能

在TypeScript 2.1之前支持此功能,但仅在定位ES6/ES2015时。TypeScript 2.1为ES3和ES5运行时提供了功能,这意味着无论您使用何种环境,您都可以自由地利用它。

注意:首先,我们需要确保我们的运行时具有全局可用的ECMAScript兼容性Promise。这可能涉及为Promise获取一个polyfill,或者依赖一个你可能在你所定位的运行时间。我们还需要确保TypeScript知道Promise是存在的,通过将lib标志设置为类似于"dom", "es2015"或"dom", "es2015.promise", "es5"的东西。

示例

tsconfig.json
{
    "compilerOptions": {
        "lib": ["dom", "es2015.promise", "es5"]
    }
}
dramaticWelcome.ts
function delay(milliseconds: number) {
    return new Promise<void>(resolve => {
        setTimeout(resolve, milliseconds);
    });
}

async function dramaticWelcome() {
    console.log("Hello");

    for (let i = 0; i < 3; i++) {
        await delay(500);
        console.log(".");
    }

    console.log("World!");
}

dramaticWelcome();

编译和运行输出应该会导致ES3/ES5引擎上的正确行为。

支持外部助手库(tslib)

TypeScript注入了一些辅助函数,例如用于继承的__extends,在对象文字中用于扩展操作的__assign和JSX元素以及用于异步函数的__awaiter。

以前有两种选择:

  1. 在每个需要它们的文件中注入帮助器,或者
  2. 没有帮助器--noEmitHelpers。

这两个选项还有待改进;将帮助器捆绑在每个文件中对于试图保持其包装尺寸较小的客户来说是一个痛点。并且不包括帮助器,意味着客户必须维护自己的帮助程序库。

TypeScript 2.1允许在项目中将这些文件包含在一个单独的模块中,编译器将根据需要向它们发出导入。

阅读剩余部分

相关阅读 >>

详解javascript是如何运行的

typescript 装饰器

typescript msbuild编译选项

typescript 2.0介绍

typescript 声明文件原理

typescript 枚举

typescript 类型兼容性

typescript 声明文件模板

typescript 模块

了解typescript和javascript之间的差异

更多相关阅读请进入《typescript》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...