[翻译]TypeScript中的satisfies运算符
direwolf
2023-11-11 0

TypeScript 4.9标准中引入了新的satisfies运算符。

原文:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html

TypeScript开发者常常面临一个困境:我们想要确保表达式符合某个类型,但为了类型推断又想保留表达式最确切的类型。

举例来说:

// 每个属性可以是字符串或者RGB元组。
const palette = {
    red: [255, 0, 0],
    green: "#00ff00",
    bleu: [0, 0, 255]
//  ^^^^ 天啊 —— 拼错了!
};
// 我们希望能在“red”上使用数组方法...
const redComponent = palette.red.at(0);
// 或者是在“green”上使用字符串方法...
const greenNormalized = palette.green.toUpperCase();

注意到我们把blue写成了bleu。我们能通过给palette添加一个类型标注来发现这处错误,但是我们也会丢失每个属性的具体类型信息。

type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette: Record<Colors, string | RGB> = {
    red: [255, 0, 0],
    green: "#00ff00",
    bleu: [0, 0, 255]
//  ~~~~ 现在这处错误被发现了
};
// 但是这里出现了一个我们不想看见的错误 —— “palette.red”有可能是一个string。
const redComponent = palette.red.at(0);

新的satisfies运算符能让我们能在不改变一个表达式结果的类型的情况下验证一个表达式是否符合某个类型。举例来说,我们可以用satisfies验证palette的所有属性都与string | number[]兼容:

type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette = {
    red: [255, 0, 0],
    green: "#00ff00",
    bleu: [0, 0, 255]
//  ~~~~ 现在这处错误被发现了!
} satisfies Record<Colors, string | RGB>;
// 这些方法都可以正常调用!
const redComponent = palette.red.at(0);
const greenNormalized = palette.green.toUpperCase();

satisfies能被用来发现很多可能的错误。举例来说,我们可以确保一个对象含有来自某个类型的所有键,但是不包含额外的键:

type Colors = "red" | "green" | "blue";
// 确保有且仅有来自“Colors”中的键
const favoriteColors = {
    "red": "yes",
    "green": false,
    "blue": "kinda",
    "platypus": false
//  ~~~~~~~~~~ 错误 —— ”platypus“不在“Colors”中
} satisfies Record<Colors, unknown>;
// “red”、“green”和“blue”的一切都得到了保留
const g: boolean = favoriteColors.green;

也许我们并不关心属性名对不对得上,而是关心各个属性的类型。在那种情形下,我们也能确保对象的属性值遵从某个类型。

type RGB = [red: number, green: number, blue: number];
const palette = {
    red: [255, 0, 0],
    green: "#00ff00",
    blue: [0, 0]
    //    ~~~~~~ 错误!
} satisfies Record<string, string | RGB>;
// 各个属性的信息依旧得到了保留。
const redComponent = palette.red.at(0);
const greenNormalized = palette.green.toUpperCase();

要获取更多例子,你可以查阅提议这项功能的issue以及实现的pr。我们要感谢Oleksandr Tarasiuk与我们一同实现与迭代这项功能。

评论 0
没有评论
评论已关闭
发表评论
评论 取消回复
Copyright © 2024 .direwolf