[ts]从类型创建类型

124 阅读2分钟

官网地址

泛型

泛型类型

function identity<Type>(arg: Type): Type {
    return arg;
}

let myIdentity: <Type>(arg: Type) => Type = identity;
interface GenericIdentityFn {
    <Type>(arg: Type): Type;
}

function identity<Type>(arg: Type): Type {
    return arg;
}

let myIdentity: GenericIdentityFn = identity;

泛型Class

class GenericNumber<NumType> {
    zeroValue: NumType;
    add: (x: NumType, y: NumType) => NumType;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
    return x + y;
};

let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function (x, y) {
    return x + y;
};

泛型约束

interface Lengthwise {
    length: number;
}

 

function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
    return arg;
}
function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

// ok
getProperty(x, "a");
// error
getProperty(x, "m");

泛型中使用class类型

function create<Type>(c: { new (): Type }): Type {
    return new c();
}
class BeeKeeper {
    hasMask: boolean = true;
}

class ZooKeeper {
    nametag: string = "Mikle";
}

class Animal {
    numLegs: number = 4;
}

class Bee extends Animal {
    keeper: BeeKeeper = new BeeKeeper();
}

class Lion extends Animal {
    keeper: ZooKeeper = new ZooKeeper();
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

createInstance(Lion).keeper.nametag;
createInstance(Bee).keeper.hasMask;

keyof类型操作符

type Point = { x: number; y: number };

// 等于 “x” | “y”
type P = keyof Point;
type Arrayish = { [n: number]: unknown };
// type A = number
type A = keyof Arrayish;

type Mapish = { [k: string]: boolean };
// type M = string | number
type M = keyof Mapish;

obj[0] 会转为obj["0"]所以类型M也可能是number类型

typeof类型操作符

在类型的上下文中,使用typeof操作符来获取变量或者属性的类型

let s = "hello";
// let n: string
let n: typeof s;

索引类型

type Person = { age: number; name: string; alive: boolean };
// type Age = number
type Age = Person["age"];
// type I1 = string | number
type I1 = Person["age" | "name"];

// type I2 = string | number | boolean
type I2 = Person[keyof Person];

type AliveOrName = "alive" | "name";
// type I3 = string | boolean
type I3 = Person[AliveOrName];

条件类型

使用三目

SomeType extends OtherType ? TrueType : FalseType;
interface Animal {
    live(): void;
}

// type Example1 = number
type Example1 = Dog extends Animal ? number : string;

条件类型约束

type MessageOf<T> = T extends { message: unknown } ? T["message"] : never;

interface Email {
    message: string;
}

interface Dog {
    bark(): void;
}

// type EmailMessageContents = string
type EmailMessageContents = MessageOf<Email>;

// type DogMessageContents = never
type DogMessageContents = MessageOf<Dog>;

条件类型内的推导

使用infer关键字

type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;
// (...args: never[]) => infer Return
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
    ? Return
    : never;

 
// type Num = number
type Num = GetReturnType<() => number>;
// type Str = string
type Str = GetReturnType<(x: string) => string>;
// type Bools = boolean[]
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>;

分布条件类型

type ToArray<Type> = Type extends any ? Type[] : never;

// type StrArrOrNumArr = string[] | number[]
type StrArrOrNumArr = ToArray<string | number>;

映射类型

映射类型基于索引签名

type OnlyBoolsAndHorses = {
    [key: string]: boolean | Horse;
};

const conforms: OnlyBoolsAndHorses = {
    del: true,
    rodney: false,
};

type OptionsFlags<Type> = {
    [Property in keyof Type]: boolean;
};

映射修饰符

可以通过+ -添加或者移除? readonly

// Removes 'readonly' attributes from a type's properties

type CreateMutable<Type> = {
    -readonly [Property in keyof Type]: Type[Property];
};
 
type LockedAccount = {
    readonly id: string;
    readonly name: string;
};

// type UnlockedAccount = { id: string; name: string; }
type UnlockedAccount = CreateMutable<LockedAccount>;
// Removes 'optional' attributes from a type's properties
type Concrete<Type> = {
    [Property in keyof Type]-?: Type[Property];
};

type MaybeUser = {
    id: string;
    name?: string;
    age?: number;
};

// type User = { id: string; name: string; age: number; }
type User = Concrete<MaybeUser>;

通过as重命名映射类型的key

type Getters<Type> = {
    [Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};

interface Person {
    name: string;
    age: number;
    location: string;
}
// type LazyPerson = { getName: () => string; getAge: () => number; getLocation: () => string; }
type LazyPerson = Getters<Person>;
// Remove the 'kind' property

type RemoveKindField<Type> = {
    [Property in keyof Type as Exclude<Property, "kind">]: Type[Property]
};

interface Circle {
    kind: "circle";
    radius: number;
}

// type KindlessCircle = { radius: number; }
type KindlessCircle = RemoveKindField<Circle>;

模板字面量类型

type World = "world";
// type Greeting = "hello world"
type Greeting = `hello ${World}`;
type PropEventSource<Type> = {
        on(eventName: `${string & keyof Type}Changed`, callback: (newValue: any) => void): void;
};

 

/// Create a "watched object" with an 'on' method
/// so that you can watch for changes to properties.
declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>;

const person = makeWatchedObject({
    firstName: "Saoirse",
    lastName: "Ronan",
    age: 26
});

person.on("firstNameChanged", () => {});
// error, Prevent easy human error (using the key instead of the event name)
person.on("firstName", () => {});

内置的操作类型

  • Uppercase<StringType>
  • Lowercase<StringType>
  • Capitalize<StringType>
  • Uncapitalize<StringType>