巧用 Typescript (二)

巧用 Typescript (二)

上一期:

王亦斯:巧用 Typescriptzhuanlan.zhihu.com图标

🌀巧用Record类型

业务中,我们经常会写枚举和对应的映射:

type AnimalType = 'cat' | 'dog' | 'frog';
const AnimalMap = {
  cat: { name: '猫', icon: '🐱'},
  dog: { name: '狗', icon: '🐶' },
  forg: { name: '蛙', icon: '🐸' },
};

注意到上面 forg 拼错了吗?

Record 可以保证映射完整:

type AnimalType = 'cat' | 'dog' | 'frog';
interface AnimalDescription { name: string, icon: string }
const AnimalMap: Record<AnimalType, AnimalDescription> = {
  cat: { name: '猫', icon: '🐱'},
  dog: { name: '狗', icon: '🐶' },
  forg: { name: '蛙', icon: '🐸' }, // Hey!
};

还能有代码提示

如果你喜欢用 enum ,写法也一样的

enum AnimalType {
  CAT = 'cat',
  DOG = 'dog',
  FROG = 'frog',
}
const AnimalMap: Record<AnimalType, AnimalDescription>

🌀巧用Partial

就是部分的意思,很常用:

const mergeOptions = (options: Opt, patch: Partial<Opt>) {
  return { ...options, ...patch };
}

class MyComponent extends React.PureComponent<Props> {
  defaultProps: Partial<Props> = {};
}


🌀巧用tsx+extends

.tsx 文件里,泛型可能会被当做 jsx 标签

const toArray = <T>(element: T) => [element]; // Error in .tsx file.

extends 可破

const toArray = <T extends {}>(element: T) => [element]; // No errors.

🌀巧用ClassOf

有时候,我们要传入类本身,而不是类的实例

abstract class Animal extends React.PureComponent {
  /* Common methods here. */
}
class Cat extends Animal {}
class Dog extends Animal {}

// `AnimalComponent` must be a class of Animal.
const renderAnimal = (AnimalComponent: Animal) => {
  return <AnimalComponent/>; // WRONG!
}

上面的代码是错的,因为 Animal 是实例类型,不是类本身。应该

interface ClassOf<T> {
  new (...args: any[]): T;
}
const renderAnimal = (AnimalComponent: ClassOf<Animal>) => {
  return <AnimalComponent/>; // Good!
}

renderAnimal(Cat); // Good!
renderAnimal(Dog); // Good!

🌀巧用类型查找+类方法

我们通常会在 React 组件中把方法传下去

class Parent extends React.PureComponent {
  private updateHeader = (title: string, subTitle: string) => {
    // Do it.
  };
  render() {
    return <Child updateHeader={this.updateHeader}/>;
  }
}

interface ChildProps {
  updateHeader: (title: string, subTitle: string) => void;
}
class Child extends React.PureComponent<ChildProps> {
  private onClick = () => {
    this.props.updateHeader('Hello', 'Typescript');
  };
  render() {
    return <button onClick={this.onClick}>Go</button>;
  }
}

其实可以在 ChildProps 中直接引用类的方法

interface ChildProps {
  updateHeader: Parent['updateHeader'];
}

两个好处:不用重复写方法签名,能从方法调用跳到方法定义 。

传统的跳转:

传统的跳转


神奇的跳转:

神奇的跳转

尤其在多层传递的场合,从孙子的一个方法调用,跳到爷爷的方法定义,爽。


有用赞一个呗。

编辑于 2019-05-01