发布于 

如何用Record类型处理不同的情况

使用TypeScript的Record类型编写更好的代码

使用场景

构造一个对象类型,其属性键为Keys,其属性值为Type。这个工具可以用来将一个类型的属性映射到另一个类型

当需要将一个类型的属性映射到另一个类型的属性时,或者当你需要定义一个严格的键值对对象时
例如,如果你想定义一个字典类型,它的键是一些字符串,它的值是一些数字,你可以这样写:

1
type Dictionary = Record<string, number>;

或者,如果你想定义一个类型,它的属性名是一些固定的字符串,它的属性值是一些函数,你可以这样写:

1
type Handlers = Record<'click' | 'hover' | 'focus', () => void>;

Record类型是一个很方便的工具类型,它可以帮助你简化和规范你的代码

需求目的

  • 属性映射
  • 规范组数据属性类型约束
1
2
3
4
5
6
7
type petsGroup = 'dog' | 'cat' | 'fish';
interface IPetInfo {
name:string,
age:number,
}

type IPets = Record<petsGroup, IPetInfo>;

这里,IPets类型是由Record<petsGroup, IPetInfo>返回的,它表示一个对象,它的key只能是dog,cat或fish中的一个,而对应的value必须是IPetInfo类型,即包含name和age字段的对象。Record类型可以让我们更清晰地表达对象的结构和约束

相关实现

除了使用Record类型来处理枚举类型,我们还可以使用它来处理联合类型。联合类型是指一个值可以是多种类型中的一种,比如:

1
type Animal = 'Dog' | 'Cat' | 'Bird';

这里我们定义了一个Animal类型,它可以是’Dog’、’Cat’或’Bird’中的任意一个。如果我们想要根据不同的Animal类型返回不同的内容,我们也可以使用Record类型来实现:

1
2
3
4
5
6
7
8
9
const animalContent: Record<Animal, JSX.Element> = {
Dog: <div>Dog is loyal and friendly.</div>,
Cat: <div>Cat is cute and independent.</div>,
Bird: <div>Bird is colorful and free.</div>,
};

function getAnimalContent(animal: Animal) {
return animalContent[animal];
}

这样就可以避免使用switch语句或if-else语句来判断animal的类型,而且也可以保证我们不会遗漏任何一种情况。如果我们添加了一个新的Animal类型,比如:

1
type Animal = 'Dog' | 'Cat' | 'Bird' | 'Fish';

我们也会立刻看到TypeScript报错,提示我们animalContent对象缺少了Fish属性:

这样就可以提醒我们及时更新animalContent对象,避免出现bug。

总结

简单来说,Record类型是TypeScript中的一个工具类型,它可以让我们定义一个对象类型,其属性键为一个已知的集合(比如枚举或联合类型),其属性值为另一个类型(比如函数或组件)。当我们使用Record类型时,TypeScript会要求我们为每个属性键提供一个对应的属性值,否则会报错。这样就可以保证我们不会遗漏任何情况,从而编写更健壮、更可维护的代码。

参考文档链接