函数参数类型

type TFuncParameterType<T> = T extends (arg: infer P) => void ? P : string;

// e.g
function func(arg: string) {}
type TParamsType = TFuncParameterType<typeof func>; // string

函数返回值类型

type TFuncReturnType<T> = T extends (arg: any) => infer P ? P : string;

// e.g
function func(arg: string): number {}
type TReturnType = TFuncReturnType<typeof func>; // number

元祖成员作为键约束

const keys = ["a", "b", "c"] as const;

type TKeysMap = Record<typeof keys[number], string> // KeysMap: { a: string; b: string; c: string; }

数组元素类型

type ArrayElement<T extends readonly unknown[]> = T extends readonly (infer P)[]
  ? P
  : never;

// e.g
const arr = [0, 1];
type TArr = ArrayElement<typeof arr> // number

值类型覆写

type Overwrite<T, R> = Omit<T, keyof R> & R;

// e.g
interface IA {
  a: number;
  b: string;
}
type TA = Overwrite<IA, {a: string}> // {a: string; b:string}

键覆写

type OverwriteKey<T, K extends keyof T, P extends keyof any> = Omit<T, K> & { [S in P]: T[K] };

// e.g
interface IA {
  a: number;
  b: string;
}
type TA = OverwriteKey<IA, "a", "c"> // {c: number; b:string}

元祖作为键约束

type TuplesAsKey<T extends readonly any[], P> = {
  [K in T[number]]: P;
};

// e.g
const keys = ["x", "y"] as const;
type TA = TuplesAsKey<typeof keys, string>; // {x: string, y: string}

函数类型省略this

type OmitThisParameter<T> = unknown extends ThisParameterType<T>
  ? T
  : T extends (...args: infer A) => infer R
  ? (...args: A) => R
  : number;


// e.g
const func = (this: void, arg: string) => {};
type TFunc = OmitThisParameter<typeof func>; // type TFunc = (arg: string) => void

继承父类方法调用返回子类

class Foo {
  static instance: any;

  static getInstance<T extends typeof Foo>(this: T): InstanceType<T> {
    if (this.instance) {
      return this.instance as InstanceType<T>;
    }
    return new this() as InstanceType<T>;
  }
}

class Bar extends Foo {}

Bar.getInstance(); // Bar

元祖类型

type _TupleOf<T, N extends number, R extends unknown[]> = R["length"] extends N ? R : _TupleOf<T, N, [T, ...R]>;
type Tuple<T, N extends number> = N extends N ? (number extends N ? T[] : _TupleOf<T, N, []>) : never;

// e.g
type TTuple = Tuple<string, 4>; // [string, string, string. string]

函数第二个参数类型有第一个参数决定(第一个参数是Key,第二个参数是Value)

export class Foo {
  private _data = {
    a: 1,
    b: "2",
  };

  public set<K extends keyof Foo["_data"]>(key: K, value: Foo["_data"][K]): void {
    this._data[key] = value;
  }
}

元祖转联合类型

const arr = <const>["foo", "bar", "baz"];

type Ts = typeof arr[number]; // "foo" | "bar" | "baz"

联合类型转元祖

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type LastOf<T> = UnionToIntersection<T extends any ? () => T : never> extends () => infer R ? R : never;

type Push<T extends any[], V> = [...T, V];

type TuplifyUnion<T, L = LastOf<T>, N = [T] extends [never] ? true : false> = true extends N
  ? []
  : Push<TuplifyUnion<Exclude<T, L>>, L>;

type Tabc = "a" | "b" | "c";
type TTuple = TuplifyUnion<abc>; // ["a", "b", "c"]

键值对的键构建联合类型

const kv = {
  foo: 1,
  bar: 2,
  baz: 3,
} as const;

type Ts = keyof typeof kv; // "foo" | "bar" | "baz;"

键值对的值构建联合类型

const kv = {
  foo: 1,
  bar: 2,
  baz: 3,
} as const;

type Ts = typeof kv[keyof typeof kv]; // 1 | 2 | 3

数组项的某一字段值构建联合类型

const kvs = [
  { name: "foo", other: "something" },
  { name: "bar", other: "something" },
  { name: "baz", other: "something" },
] as const;

type Ts = typeof kvs[number]["name"]; // "foo" | "bar" | "baz"

合并联合键值对类型

type FnReturnType<T> = T extends (...args: any) => infer R ? (R extends void ? {} : R) : {};

type AllKeys<T> = T extends any ? keyof T : never;

type CommonKeys<T extends object> = keyof T;

type Subtract<A, C> = A extends C ? never : A;

type NonCommonKeys<T extends object> = Subtract<AllKeys<T>, CommonKeys<T>>;

type PickType<T, K extends AllKeys<T>> = T extends { [k in K]?: any } ? T[K] : undefined;

type PickTypeOf<T, K extends string | number | symbol> = K extends AllKeys<T> ? PickType<T, K> : never;

type Merge<T extends object> = {
  [k in CommonKeys<T>]: PickTypeOf<T, k>;
} & {
  [k in NonCommonKeys<T>]?: PickTypeOf<T, k>;
};

type PartialMerge<T extends object> = {
  [k in CommonKeys<T>]?: PickTypeOf<T, k>;
} & {
  [k in NonCommonKeys<T>]?: PickTypeOf<T, k>;
};

type A = { a: string } | { a: string; b: string } | { a: string; c: boolean };

type B = PartialMerge<A>; // { a?: string; b?:string; c?: boolean; }
type C = Merge<A>; // { a: string; b?:string; c?: boolean}