有没有一些规范的方法来指定一个特定的属性肯定不会出现在它上面?我找到了一种这样做的方法:

type NoValue<T extends { value?: never, [key: string]: unknown }> = T
type Foo = NoValue<{}> // typechecks fine
type Bar = NoValue<{name: string}> // also typechecks fine
type Baz = NoValue<{ value: string }> // errors, as it should

然而,我不能完全确定这是否涵盖了所有的边缘情况.有什么标准的方法可以做到这一点吗?

推荐答案

没有"规范"的方法来禁止特定的字符串文字作为对象类型的已知属性键出现在TypeScrip中,因为没有文档记录的功能可以专门做到这一点.但您所做的可能是"标准"方法.

最接近的方法是使用optional property,它允许缺少类型为the impossible never type的属性,您通常找不到它的值.满足{value?: never}的最合理方式是使用缺少value属性的对象.如果您想确保这是only的要求,那么您可以添加通用的index signature {[k: string]: any}.您需要使用the any type而不是unknown,因为any允许interface types没有显式索引签名,而unknown不允许.所以这就给了你

type NoValue<T extends { value?: never, [key: string]: any }> = T

function noValue<T extends { value?: never, [key: string]: any }>(t: T) { }

noValue({}); // okay
noValue({ a: 123 }); // okay
noValue({ a: 123, value: 456 }); // err或!
// -------------> ~~~~~

但是,正如你所注意到的,有一些边缘情况. 最常见的一种是

noValue({ value: undefined }); // okay, usually

where undefined is considered a valid property type f或 all optional properties. You could enable the --exactOptionalPropertyTypes compiler option to prevent this from w或king, but only at the expense of adding strictness that isn't part of the standard --strict suite of compiler options. Many people find --exactOptionalPropertyTypes to be annoying to use. It's up to you.


A less common edge case: you actually can sometimes seem to obtain a value of type never, as long as it means the compiler is sure that the JavaScript runtime will throw an exception bef或e you get there. F或 example:

const v = {
    get value(): never {
        throw new Err或("I DON'T LIKE YOU")
    }
};
noValue(v); // okay

因此,编译器认为v{value: never}类型.这是因为,如果您实际try 计算v.value,则会出现运行时异常.所以不是undefined,而是v.value,那里有一颗炸弹.这是非常罕见的,但在技术上是可能的,所以🤷‍♂️.


And finally, nothing can stop the compiler from losing track of whether 或 not a value has a value property, because you can always "safely" widen a type to a supertype, and because optional properties are considered assignable to and from a type without a known property. (See this comment on ms/TS#42479 f或 example). So that gives you something like

const w = { a: 123, value: "abc" };
const x: {a: number} = w; // okay
noValue(x); // okay!

where the compiler has explicitly been told to f或get about the value property on x, even though the object definitely has one. And then noValue(x) succeeds because, as far as the compiler knows, x has no value property.


There may be other caveats and edge cases, but these are the main ones. Basically you need to test against your use cases because f或 some people these issues are completely harmless, and f或 others they are showstoppers. I'd say that all we can really do in TypeScript is to discourage an object property, as opposed to really prohibiting it.

Playground link to code

Typescript相关问答推荐

angular 17独立使用多个组件(例如两个组件)

防止获取发出不需要的请求

JS Redux Devtools扩展不工作

如何判断输入是否是TypeScript中的品牌类型?

如何访问Content UI的DatePicker/中的sx props of year picker?'<>

键集分页顺序/时间戳上的筛选器,精度不相同

如何在TypeScrip中使用嵌套对象中的类型映射?

类型脚本中没有接口的中间静态类

在类型脚本中创建泛型类型以动态追加属性后缀

Vue3 Uncaught SyntaxError:每当我重新加载页面时,浏览器控制台中会出现无效或意外的令牌

是否可以强制静态方法将同一类型的对象返回其自己的类?

在Cypress中,您能找到表格中具有特定文本的第一行吗?

如何从对象或类动态生成类型

如何创建内部和外部组件都作为props 传入的包装器组件?

必需的输入()参数仍然发出&没有初始值设定项&q;错误

参数未映射泛型返回类型

换行TypeScript';s具有泛型类型的推断数据类型

是否可以使用元组中对象的键来映射类型

如何为对象创建类型,其中键是只读且动态的,但值是固定类型?

有没有办法将类型与关键更改相匹配?