Typescript 4.1新特性一览

933 阅读1分钟

模板字符串类型(Template Literal Types)

它的语法与ES6的模板字符串相似,只是用于类型。此外,用在模板字符串类型中的泛型或类型别名,类型必须满足是string | number | bigint | boolean | null | undefined之一。

type TestError<T> = `${T}Changed`; // error: Type 'T' is not assignable to type 'string | number | bigint | boolean | null | undefined'.
type EventName<T extends string> = `${T}Changed`;
type T0 = EventName<'foo'>;  // 'fooChanged'
type T1 = EventName<'foo' | 'bar' | 'baz'>;  // 'fooChanged' | 'barChanged' | 'bazChanged'

字符串模板中的联合类型会进行排列组合(生成每个联合类型成员表示的所有可能的字符串字面量的集合)

type Color = "red" | "blue";
type Quantity = "one" | "two";


type SeussFish = `${Quantity | Color} fish`;
// "one fish" | "two fish" | "red fish" | "blue fish"

为了更方便对字符串字面量进行操作,Typescript4.1新增了几个预定义的类型别名,分别是UppercaseLowercaseCapitalizeUncapitalize。 分别是大写、小写,首字母大写,首字母小写。

type Test<T extends string> = `${Uppercase<T>} ${Lowercase<T>} ${Capitalize<T>} ${Uncapitalize<T>}`;

type T = Test<'test'>
// TEST test Test test

类比Typescript 4.0推出的可变元祖类型,其实模板字符串也可以叫做“可变字符串类型”。此特性的推出大大增强了对字符串字面量的操作。

映射类型中支持键名重新映射(Key Remapping in Mapped Types)

映射类型可以根据提供的键生成新的对象类型,而要根据输入来创建新键或是过滤键的话,老版本的Typescript是无能为力的。

// 两例都是根据提供的键生成新的对象类型,无法对键做进一步操作
type Options = {
    [K in "noImplicitAny" | "strictNullChecks" | "strictFunctionTypes"]?: boolean
};

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

TypeScript 4.1 允许使用as 字句对键名重新映射。

// 过滤掉传入类型的kind属性
type RemoveKindField<T> = {
    [K in keyof T as Exclude<K, "kind">]: T[K]
};

// 传入类型键名首字母大写,前面加get
type Getters<T> = {
    [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

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

type LazyPerson = Getters<Person>;
/*
{
    getName: () => string;
    getAge: () => number;
    getLocation: () => string;
}
*/

条件类型可递归

Typescript 4.1 支持在条件类型的分支中引用自身(递归)

type ElementType<T> =
    T extends ReadonlyArray<infer U> ? ElementType<U> : T;

function deepFlatten<T extends readonly unknown[]>(x: T): ElementType<T>[] {
    // ...
}

// All of these return the type 'number[]':
deepFlatten([1, 2, 3]);
deepFlatten([[1], [2, 3]]);
deepFlatten([[1], [[2]], [[[3]]]]);

参考资料