如何提升我的 TypeScript 技能 #5:满足运算符
我将与大家分享一些提升我 TypeScript 技能的技巧!今天我们将学习satisfies4.9 TS 更新中出现的运算符!
一个“无聊的”错误
我们来看一下使用带有多个值的 Record 时常见的错误。
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",
blue: [0, 0, 255]
};
const redComponent = palette.red.at(0); // Property 'at' does not exist on type 'string | RGB'.
嗯……这真的很无聊,我们不能直接使用,array methods因为 TypeScript 不知道red属性是 astring还是RGBtype!这是因为我们使用了Record<Colors, string | RGB>.
stringTypeScript 无法确定和之间的正确类型RGB。
第一种方法:缩小范围
我们可以缩小类型范围!
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",
blue: [0, 0, 255]
};
function setColor(color: RGB | string) {
if (color instanceof Array) {
return color.forEach(); // We can use array methods
} else {
return color.toUpperCase(); // It's a string ! So we can use String methods
}
}
这是一个解决方案,但我们需要添加用于输入内容的运行代码。
第二种解决方案:无类型
您可以通过移除类型来解决这个问题。
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
};
const redComponent = palette.red.at(0);
这也是一个“糟糕”的解决方案,为什么呢?因为你没有输入框,所以可能会输入错误的键或者出现拼写错误!
const palette = {
red: [255, 0, 0],
green: null, // It should throw error
bleu: [0, 0, 255] // It should throw error since it's not 'bleu' but 'blue'
};
第三种解决方案:作为常量
简要介绍一下as const`.` : as const`.` 用于阻止对变量的任何编辑,例如 `const` 赋值。这种阻止作用使得 TypeScript 能够通过更多细节来缩小正确类型的范围。
const a: string = 'hello' // is string
const b = 'hello' as const // is 'hello'
我们来试试!
const palette = {
"red": "yes",
"green": false,
"fakeKey": false, // It should throw error
"bleu": "kinda", It should throw error
} as const;
所以它和旧方案一样,没有严格的类型限制!因此它可能导致错误wrong key或错误misstypo!
最后一种解决方案:从基本类型创建特定类型
为了实现正确的缩小范围,您还可sub type以为每个对象创建特定的范围。
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
type One = Record<"red", RGB> & Record<"green" | "blue", string>
const palette: One = {
red: [255, 0, 0],
green: "#00ff00",
blue: "#00ff00"
}
palette.red // RGB
palette.blue // string
如果筛选条件正确,那就太好了!但如果你有很多键和值,我得说:Good luck我的朋友。
所以,时候到了……
满意了,我们开始吧
新的满足运算符允许我们验证表达式的类型是否与某种类型匹配,而不会改变该表达式的结果类型。
TypeScript 开发人员经常面临一个两难困境:我们希望确保某个表达式与某个类型匹配,但同时也希望保留该表达式最具体的类型以进行类型推断。
例如,我们可以使用 satifies 来验证 palette 的所有属性是否与 string | number[] 兼容。
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
} satisfies Record<Colors, string | RGB>
palette.red // RGB !
palette.green // string !
它捕获了所有可能的输入错误。
const palette = {
red: [255, 0, 0],
green: "#00ff00",
wrongKey: "#00ff00", // Catch Error !
bleu: [0, 0, 255], // Catch Error !
} satisfies Record<Colors, string | RGB>
palette.green = [0, 0, 255] // ! green is basically string, it cannot be RGB !
我们解决了这个问题!
如果让我对satifies运算符给出一个简短的定义,应该是这样的:
satisfies operator check a type like Record<string, A | B>, and narrow the correct type between A | B for each key
奖励,满足 + 作为常量
您可以添加所有as const与以下组合带来的益处satifies:
在这个例子中:
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
} satisfies Record<Colors, string | RGB>
palette.red是RGB,不是[255, 0, 0]。这是正常的,因为我们可以用另一个 RGB 值来编辑 palette.red,例如[255, 255, 255]!
如果你需要这个strict value type,你可以使用as const。
type Colors = "red" | "green" | "blue";
// We use Readonly utils type for using as const
type RGB = Readonly<[red: number, green: number, blue: number]>
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
} as const satisfies Record<Colors, string | RGB>
palette.red // [255, 0, 0]
palette.red = [255, 255, 0] // throw error since we cannot edit an property that is constant
希望您喜欢这篇文章!
☕️ 您可以支持我的作品🙏
🏃♂️ 你可以关注我 👇
🕊 Twitter:https://twitter.com/code__oz
👨💻 Github:https://github.com/Code-Oz
🇫🇷🥖 对于法国开发者,您可以查看我的YouTube 频道
您可以收藏这篇文章!
文章来源:https://dev.to/codeoz/how-i-improve-my-skills-in-typescript-5-satisfies-operator-2312