周报@2023-04-13
TypeScript 4.9 的新特性
The satisfies Operator
https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/#the-satisfies-operator
TypeScript developers are often faced with a dilemma: we want to ensure that some expression matches some type, but also want to keep the most specific type of that expression for inference purposes.
For example:
1// Each property can be a string or an RGB tuple.
2const palette = {
3 red: [255, 0, 0],
4 green: "#00ff00",
5 bleu: [0, 0, 255]
6// ^^^^ sacrebleu - we've made a typo!
7};
8
9// We want to be able to use array methods on 'red'...
10const redComponent = palette.red.at(0);
11
12// or string methods on 'green'...
13const greenNormalized = palette.green.toUpperCase();
Notice that we’ve written bleu
, whereas we probably should have written blue
. We could try to catch that bleu
typo by using a type annotation on palette
, but we’d lose the information about each property.
1type Colors = "red" | "green" | "blue";
2
3type RGB = [red: number, green: number, blue: number];
4
5const palette: Record<Colors, string | RGB> = {
6 red: [255, 0, 0],
7 green: "#00ff00",
8 bleu: [0, 0, 255]
9// ~~~~ The typo is now correctly detected
10};
11
12// But we now have an undesirable error here - 'palette.red' "could" be a string.
13const redComponent = palette.red.at(0);
The new satisfies
operator lets us validate that the type of an expression matches some type, without changing the resulting type of that expression. As an example, we could use satisfies
to validate that all the properties of palette
are compatible with string | number[]
:
1type Colors = "red" | "green" | "blue";
2
3type RGB = [red: number, green: number, blue: number];
4
5const palette = {
6 red: [255, 0, 0],
7 green: "#00ff00",
8 bleu: [0, 0, 255]
9// ~~~~ The typo is now caught!
10} satisfies Record<Colors, string | RGB>;
11
12// Both of these methods are still accessible!
13const redComponent = palette.red.at(0);
14const greenNormalized = palette.green.toUpperCase();
satisfies
can be used to catch lots of possible errors. For example, we could ensure that an object has all the keys of some type, but no more:
1type Colors = "red" | "green" | "blue";
2
3// Ensure that we have exactly the keys from 'Colors'.
4const favoriteColors = {
5 "red": "yes",
6 "green": false,
7 "blue": "kinda",
8 "platypus": false
9// ~~~~~~~~~~ error - "platypus" was never listed in 'Colors'.
10} satisfies Record<Colors, unknown>;
11
12// All the information about the 'red', 'green', and 'blue' properties are retained.
13const g: boolean = favoriteColors.green;
Maybe we don’t care about if the property names match up somehow, but we do care about the types of each property. In that case, we can also ensure that all of an object’s property values conform to some type.
1type RGB = [red: number, green: number, blue: number];
2
3const palette = {
4 red: [255, 0, 0],
5 green: "#00ff00",
6 blue: [0, 0]
7 // ~~~~~~ error!
8} satisfies Record<string, string | RGB>;
9
10// Information about each property is still maintained.
11const redComponent = palette.red.at(0);
12const greenNormalized = palette.green.toUpperCase();
For more examples, you can see the issue proposing this and the implementing pull request. We’d like to thank Oleksandr Tarasiuk who implemented and iterated on this feature with us.
布尔逻辑运算符 - AND、OR、NOT、XOR
逻辑布尔运算符使用 bool 操作数执行逻辑运算。 运算符包括一元逻辑非 (!
)、二元逻辑 AND (&
)、OR (|
) 以及异或 (^
),二元条件逻辑 AND (&&
) 和 OR (||
)。
- 一元
!
(逻辑非)运算符。 - 二元
&
(逻辑与)、|
(逻辑或)和^
(逻辑异或)运算符。 这些运算符始终计算两个操作数。 - 二元
&&
(条件逻辑与)和||
(条件逻辑或)运算符。 这些运算符仅在必要时才计算右侧操作数。
JavaScript 的 BigInt 异或运算非常差,建议 Rust 重写这部分
error TS2310: Type 'Matchers<R, T>' recursively references itself as a base type.
how to fix it? add "skipLibCheck": true
to your tsconfig.json
1{
2 "compilerOptions": {
3 "target": "ESNext",
4 "module": "ESNext",
5 "moduleResolution": "node",
6 "allowSyntheticDefaultImports": true,
7 "alwaysStrict": true,
8 "sourceMap": true,
9 "forceConsistentCasingInFileNames": true,
10 "noFallthroughCasesInSwitch": true,
11 "noImplicitReturns": true,
12 "noUnusedLocals": true,
13 "noUnusedParameters": true,
14 "noImplicitAny": false,
15 "noImplicitThis": false,
16 "strictNullChecks": false,
17 "strict": true,
18 "outDir": "dist",
19 "baseUrl": ".",
20 "paths": {
21 "@/*": ["./src/*"]
22 },
23 "skipLibCheck": true
24 },
25 "include": ["src/**/*.ts"]
26}