关键词
- 联合类型(Unions)
- 泛型(Generics)
- 结构类型、鸭子类型(Structural)
- 单元类型(Unit)
- 命名类型(Named)
- 类型别名(Type Alias)
- 上下文类型(Contextual)
- 类型推断(Type Inference)
- 类型参数(Type Parameters)
- 高级类型(Higher-kinded)
- 后置类型标注(Postfix Annotation)
- 映射类型(Mapped Type)
- 类型断言(Type Assertion)
书单
特性
Intersections
// @refer: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#intersections// Intersections// In addition to unions, TypeScript also has intersections:type Combined = { a: number } & { b: string };type Conflicting = { a: number } & { a: string };// Combined has two properties, a and b, just as if they had been written as one object literal type. Intersection and union are recursive in case of conflicts, so Conflicting.a: number & string.
Type Widen
// @refer: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#unit-typesdeclare function pad(s: string, n: number, direction: "left" | "right"): string;pad("hi", 10, "left");let s = "right";pad("hi", 10, s); // error: 'string' is not assignable to '"left" | "right"'// Argument of type 'string' is not assignable to parameter of type '"left" | "right"'.let s: "left" | "right" = "right";pad("hi", 10, s);// Working around the problem with a type annotation for s, but that in turn prevents assignments to s of variables that are not of type "left" | "right".
Weird Contextual typing
// @refer: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#contextual-typingdeclare function map<T, U>(f: (t: T) => U, ts: T[]): U[];let sns = map((n) => n.toString(), [1, 2, 3]);// inference will work in any order, but intellisense will only work left-to-right, so TypeScript prefers to declare map with the array first:declare function map<T, U>(ts: T[], f: (t: T) => U): U[];
newtype
// @refer: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#type-aliasestype FString = string & { __compileTimeOnly: any };// An FString is just like a normal string, except that the compiler thinks it has a property named __compileTimeOnly that doesn’t actually exist. This means that FString can still be assigned to string, but not the other way round.
Use Type Parameters when necessary
// TypeScript can usually infer type arguments from a call based on the type of the arguments, so type arguments are usually not needed.
// Because TypeScript is structural, it doesn’t need type parameters as much as nominal systems. Specifically, they are not needed to make a function polymorphic. Type parameters should only be used to propagate type information, such as constraining parameters to be the same type:
function length<T extends ArrayLike<unknown>>(t: T): number {}
function length(t: ArrayLike<unknown>): number {}
// In the first length, T is not necessary; notice that it’s only referenced once, so it’s not being used to constrain the type of the return value or other parameters.
Avoid Point-free
Point-free programming — heavy use of currying and function composition — is possible in JavaScript, but can be verbose. In TypeScript, type inference often fails for point-free programs, so you’ll end up specifying type parameters instead of value parameters. The result is so verbose that it’s usually better to avoid point-free programming.
