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

内容预览已结束

此内容需要会员权限。请先登录以查看完整内容。