`any` is convenient, as it basically disables all type-checks[1]fetch#
async function loadProducts(): Promise<Product[]> {
const response = await fetch('https://api.mysite.com/products')
const products: unknown = await response.json()
return products as Product[]
}
type assertion#
const a = expr as any as T; // use two assertions,针对 ts 断言报错,实际上合法的
// or
const a = <T> expr;
// Non-null Assertion Operator (Postfix !)
function liveDangerously(x?: number | null) {
// No error
console.log(x!.toFixed());
}
type predicates#
function isArrayOfProducts (obj: unknown): obj is Product[] {
return Array.isArray(obj) && obj.every(isProduct)
}
function isProduct (obj: unknown): obj is Product {
return obj != null
&& typeof (obj as Product).id === 'string'
}
async function loadProducts(): Promise<Product[]> {
const response = await fetch('https://api.mysite.com/products')
const products: unknown = await response.json()
if (!isArrayOfProducts(products)) {
throw new TypeError('Received malformed products API response')
}
return products
}
narrowing for union#
// never for exhaustiveness checking
type Shape = Circle | Square;
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
readonly#
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = getReadOnlyStringArray();
myArray[2] = "Mallory";
Index signature in type 'ReadonlyStringArray' only permits reading.
infer#
- 条件类型为我们提供了一种使用 infer 关键字从 true 分支中与之进行比较的类型中进行推断的方法
- 使用 infer 关键字编写一些有用的助手类型别名
// <1>
type Flatten<Type> = Type extends Array<infer Item>
? Item
: Type;
// <2>
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
? Return
: never;
type Num = GetReturnType<() => number>; // type Num = number
type Str = GetReturnType<(x: string) => string>; // type Str = string
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; // type Bools = boolean[]
// <3> returns a similar function type, but without the first argument.
type OmitFirstArg<F> = F extends (first: any, ...rest: infer A) => infer R
? (...args: A) => R
: never;
createInstance#
/*class BeeKeeper {
hasMask: boolean;
}
class ZooKeeper {
nametag: string;
}
class Animal {
numLegs: number;
}
class Bee extends Animal {
keeper: BeeKeeper;
}
class Lion extends Animal {
keeper: ZooKeeper;
}*/
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
//createInstance(Lion).keeper.nametag;
//createInstance(Bee).keeper.hasMask;
type 三目运算#
// SomeType extends OtherType ? TrueType : FalseType;
type NameOrId<T extends number | string> = T extends number
? IdLabel
: NameLabel;
function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
throw "unimplemented";
}
let a = createLabel("typescript"); // ^ = let a: NameLabel
let b = createLabel(2.8); // ^ = let b: IdLabel
let c = createLabel(Math.random() ? "hello" : 42); // ^ = let c: NameLabel | IdLabel