194 - 《Total TypeScript Tips 笔记》
发布于 2022年10月9日
1、从对象派生出 Union 类型
const foo = {
a: 1, b: 2, c: 3,
};
type Foo = typeof foo;
type Bar = {
[K in keyof Foo]: {
[K2 in K]: number
};
}[keyof Foo];
const bar: Bar = {
a: 1
};
2、Union 类型转换,比如添加额外属性
type Foo = { type: 'user' } | { type: 'post' };
// 目标类型
// type Bar = { type: 'user', userId: string } | { type: 'post', postId: string };
type Bar = {
[Type in Foo["type"]]: { type: Type } & Record<`${Type}Id`, string>
}[Foo["type"]];
const bar: Bar = {
type: 'user',
userId: '1234',
};
3、解码 URL 搜索参数
import { String, Union } from "ts-toolbelt";
const query = `home?a=foo&b=bar`;
type Query = typeof query;
type SecondQueryPart = String.Split<Query, "?">[1];
type QueryElements = String.split<SecondQueryPart, "&">;
type QueryParams = {
[QueryElement in QueryElements[number]]: {
[key in String.Split<QueryElement, "=">[0]]: String.split<QueryElement, "=">[1]
}
}[QueryElements[number]];
// 合并 Union 为 Object
const obj: Union.Merge<QueryParams> = {
a: "foo"
};
4、利用函数重载和泛型定义 compose 函数
function compose<Input, FirstArg>(
func: (input: Input) => FirstArg,
): (input: Input) => FirstArg;
function compose<Input, FirstArg, SecondArg>(
func: (input: Input) => FirstArg,
func2: (input: FirstArg) => SecondArg,
): (input: Input) => SecondArg;
function compose<Input, FirstArg, SecondArg, ThirdArg>(
func: (input: Input) => FirstArg,
func2: (input: FirstArg) => SecondArg,
func3: (input: SecondArg) => ThirdArg,
): (input: Input) => ThirdArg;
function compose(...args: any[]) {
return {} as any;
}
const addOne = (a:number) => a + 1;
const numToString = (a:number) => a.toString();
const stringToNum = (a:string) => parseInt(a);
const x = compose(addOne, numToString, stringToNum);
x(1);
5、利用 extends 缩小泛型的范围
const getDeepValue = <
Obj,
FirstKey extends keyof Obj,
SecondKey extends keyof Obj[FirstKey],
>(
obj: Obj,
firstKey: FirstKey,
secondKey: SecondKey,
): Obj[FirstKey][SecondKey] => {
return {} as any;
}
const obj = {
foo: { f: true, b: 2 }
};
const x = getDeepValue(obj, 'foo', 'f');
7、实现 PropsFrom 从组件中提取 props
import React from 'react';
const MyComponent = (props: { enable: boolean }) => null;
class MyOtherComponent extends React.Component<{ enable: boolean }> {}
type PropsFrom<TComponent> =
TComponent extends React.FC<infer Props>
? Props
: TComponent extends React.Component<infer Props