没有强制转换的内联提示对象文字 属性?

Inline-hint object literal property without coercion?

我有一个大对象文字,类型推断是完美的,除了一个 属性,我必须转换它:

const obj = {
    a: 'big',
    ol: 'object',
    with: 'a lot of properties',
    nums: [] as number[], // would be undefined[] or unknown[] without cast
}

除了 as 让我厌烦并出现在我的 linter 和我的 运行 总强制计数器中之外,这非常有效。我也可以在单独的一行上执行 const nums: number[] = [],但随后我对真正的一个对象使用了多个声明。写出整个界面是不必要和冗长的。是否有任何类型的内联软转换或提示,以便我可以通过 as 的内联性获得 : number[] 的好处?尖括号转换也让我的 linter 很生气,而且我正在使用 JSX。

您正在寻找 microsoft/TypeScript#7481 中要求的类似“仅扩展断言”或“satisfies 运算符”之类的东西。这个想法是你会写一些像

const obj = {
  a: 'big',
  ol: 'object',
  with: 'a lot of properties',
  nums: [] satisfies number[] // <-- not valid as of TS4.5
}

并且编译器会根据上下文将 [] 解释为可分配给 number[] 的类型,如果不能则给出错误。这比 type assertion (您称之为“强制转换”或“强制转换”)更安全,后者允许您不安全地将值缩小为类型。目前 "hello" as "goodbye" 是允许的,但 "hello" satisfies "goodbye" 将是一个错误。

无论如何,目前在 TypeScript 中没有内置的方法可以做到这一点。 最近在 microsoft/TypeScript#46872 and microsoft/TypeScript#46878, and there's a possible implementation at microsoft/TypeScript#46827 中进行了设计讨论。但尚不清楚这何时会成为语言。目前只有解决方法。


一个常见的解决方法是使用通用的辅助身份函数:

const satisfies = <T,>(x: T) => x;

然后写satisfies<Type>(value)代替value satisfies Type

const obj = {
  a: 'big',
  ol: 'object',
  with: 'a lot of properties',
  nums: satisfies<number[]>([]) // <-- this works
}

/* const obj: {
    a: string;
    ol: string;
    with: string;
    nums: number[];
} */

现在,编译器会根据需要将 nums 视为类型 number[]。此版本的 satisfies 在类型断言成功的情况下也会给出编译器错误:

"hello" as "goodbye"; // no error
satisfies<"goodbye">("hello") // error!

所以这个解决方法与当前 TypeScript 中的一样好。是的,它具有可观察到的 运行 时间效应,因为发出的 JavaScript 现在有一个额外的函数调用,但这是一个相当无害的变化。如果您只打算在您的代码库中执行一次这样的操作,那么您不妨编写 const nums: number[] = []。但是,如果您 运行 至少两次遇到这个问题,那么 satisfies 辅助函数可能会物有所值。

Playground link to code