英文:
How to define type of object that does not have a specific field, even not set to undefined?
问题
interface BaseType {
baseField: string;
}
function combine<T extends Record<string, any>>(base: BaseType, addition: T) {
if ('baseField' in addition) {
throw new Error('addition should not have baseField');
}
return { ...base, ...addition };
}
const myBase: BaseType = {
baseField: "xyz"
}
const myAddition = {
otherField: 123
}
const ret = combine(myBase, myAddition);
// --> ret = { baseField: "xyz", otherField: 123 }
console.log(ret);
interface BaseType {
baseField: string;
}
type RestrictionType = Record<string, never>;
function combine<T extends RestrictionType>(base: BaseType, addition: T) {
return { ...base, ...addition };
}
const myBase: BaseType = {
baseField: "xyz"
}
const myAddition = {
otherField: 123,
baseField: undefined // This will trigger an error now
}
const ret = combine(myBase, myAddition);
// --> Error: Type 'undefined' is not assignable to type 'never'.
console.log(ret);
Here are the translated code snippets as per your request.
英文:
<!-- language-all: typescript -->
I have code like this:
interface BaseType {
baseField: string;
}
function combine<T extends Object>(base: BaseType, addition: T) {
if('baseField' in addition)
throw new Error('addition should not have baseField');
return {...base, ...addition};
}
const myBase : BaseType = {
baseField: "xyz"
}
const myAddition = {
otherField: 123
}
const ret = combine(myBase, myAddition);
// --> ret = { baseField: "xyz", otherField: 123}
console.log(ret);
I would like to use TypeScript's type definition capabilities to trigger a IDE/compiler warning/error if combine()
's addition
argument leads to baseField
getting overridden. With my current setup, I only get info about it when it's already "too late", i.e. during runtime.
I tried solutions as described in answers to questions like https://stackoverflow.com/questions/73219479/typescript-type-with-prohibited-properties-names. While solutions like this are good in many scenarios, they do not work for addition.baseField = undefined
. As example, this does not trigger any warning:
interface BaseType {
baseField: string;
}
type RestrictionType = Object & {
baseField?: never
}
function combine<T extends RestrictionType>(base: BaseType, addition: T) {
return {...base, ...addition};
}
const myBase : BaseType = {
baseField: "xyz"
}
const myAddition = {
otherField: 123,
baseField: undefined // set baseField explicitly to undefined
}
const ret = combine(myBase, myAddition); // no warning because undefined actually seems to match the "never" type
// --> ret = { baseField: undefined, otherField: 123 } // baseField got overridden
console.log(ret);
So how can I specify a type of an object where a field of a specific name must not be set, not even to undefined
?
Here's a link to a TypeScript Playground.
答案1
得分: 2
以下是已翻译的内容:
如我所理解,默认情况下,可选属性与undefined
属性完全相等;TypeScript的类型系统只是不区分它们。
TypeScript确实提供了一个选项,--exactOptionalPropertyTypes
,可以改变这一点。使用该选项,您的代码会产生所需的警告(Playground链接)。
不幸的是,根据我的有限经验,启用--exactOptionalPropertyTypes
可能需要进行相当大的代码更改。在我理想的情况下,TypeScript会让您为特定类型选择此行为。然而,这似乎是一个相当小众的请求。
英文:
As I understand it, an optional property by default is exactly equal to an undefined
property; TypeScript's type system simply doesn't distinguish between the two.
TypeScript does offer an option, --exactOptionalPropertyTypes
, that changes this. With that option, your code throws a warning, as desired (Playground link).
Unfortunately, based on my limited experience, enabling --exactOptionalPropertyTypes
may require pretty invasive code changes. In my ideal world, TypeScript would let you opt in to this behavior for specific types. However, this appears to be a fairly niche request.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论