TypeScript 4.9 - satisfies 操作符使用方法

TypeScript 4.9 官方版本发布链接

https://devblogs.microsoft.com/typescript/announcing-typescript-4-9-beta/#the-satisfies-operator

The new satisfies operator lets us validate that the type of an expression matches some type, without changing the resulting type of that expression.

新的 satisfies 操作符可以验证表达式的类型是否匹配某种类型,而不更改该表达式的结果类型。

这句话怎么理解呢?什么是:不改变表达式的结果类型?


/* 声明一个类型 TypeA */
interface TypeA {
  amount: number | string
}

const record = {
  amount: 20
} satisfies TypeA

/**
上面的写法:
既保证了 record 是符合 TypeA 类型的,
又不影响 record 的实际类型 为 :
{ 
  amount : number 
} 

所以在用 record.amount.toFixed(2) 时,
不必进行强制类型转换:
const num = record.amount as number 
num.toFixed(2)

**/

satisfies 可以用来捕获很多潜在的错误,确保一个对象是否符合某种数据类型(但不会改变对象本身的类型)。


正文

下面我们举例介绍 satisfies 的使用场景。

旧版本的类型匹配

在说明之前,我们先来看一个以前旧时代的类型匹配 case :


interface IConfig {
  a: string | number
}

/**
 * 🟡 case 1 - 以前的写法,第一行声明会报错,
 *              但使用 legacy.a 时不会报错,(不报错不行,因为a未定义)
 */
const legacy: IConfig = {}
//    ^^^^^^ 类型 "{}" 中缺少属性 "a",但类型 "IConfig" 中需要该属性。
legacy.a 
//     ^ (property) IConfig.a: string | number

/**
 * 🔴 case 2 - 以前的另一种写法,声明和使用都不会报错,大错特错!
 */
const legacyAs = {} as IConfig
// Not error
legacyAs.a
//       ^ (property) IConfig.a: string | number

4.9 新版本的写法 :satisfies

在 TS 4.9 后,为了解决以上问题,我们应该如下编码:

interface IConfig {
  a: string | number
}

/**
 * 🟢 case 3 - 新写法,可以看到第一行声明会报错,
 *              使用时也会报错,两全其美,很 nice 
 */
const current = {} satisfies IConfig
//                           ^^^^^^^ 类型“{}”不满足预期类型“IConfig”。
current.a
//      ^ 类型“{}”上不存在属性“a”

/**
 * 🟢 case 4 - 我们基于 case 4 把值加上,
 *    发现此时使用 a 的时候会自动推断我们声明的类型了!不再是联合类型。
 */
const currentWithValue = { a: 2 } satisfies IConfig
// Not error
currentWithValue.a.toFixed()
//               ^ (property) a: number 🥰


TS 4.9 以后,想写 as 的时候多想想,是不是应该用 satisfies 😎 了 ?

Ref:

posted @ 2022-12-06 11:33  炎黄子孙,龙的传人  阅读(1394)  评论(0编辑  收藏  举报