如何定义一个没有特定字段的对象类型,甚至没有设置为undefined?

huangapple go评论118阅读模式
英文:

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&lt;T extends Object&gt;(base: BaseType, addition: T) {
    if(&#39;baseField&#39; in addition)
        throw new Error(&#39;addition should not have baseField&#39;);
    return {...base, ...addition};
}

const myBase : BaseType = {
    baseField: &quot;xyz&quot;
}

const myAddition = {
    otherField: 123
}

const ret = combine(myBase, myAddition);
// --&gt; ret = { baseField: &quot;xyz&quot;, 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 &amp; {
    baseField?: never
}

function combine&lt;T extends RestrictionType&gt;(base: BaseType, addition: T) {
    return {...base, ...addition};
}

const myBase : BaseType = {
    baseField: &quot;xyz&quot;
}

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 &quot;never&quot; type
// --&gt; 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.

huangapple
  • 本文由 发表于 2023年5月29日 22:47:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76358299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定