【问题标题】:Typescript Type 'never': how to use for object fields?打字稿类型“从不”:如何用于对象字段?
【发布时间】:2021-10-04 21:37:32
【问题描述】:

我正在尝试让 this examplethis 一样工作:

interface Foo {
    a: number;
    b: string;
    c: boolean;
}

type Explode<T> = keyof T extends infer K
    ? K extends unknown
    ? { [I in keyof T]: I extends K ? T[I] : never }
    : never
    : never;


type Test = Explode<Foo>;

const test: Test = {a: 1};

这给了我以下错误:

Type '{ a: number; }' is not assignable to type '{ a: number; b: never; c: never; } | { a: never; b: string; c: never; } | { a: never; b: never; c: boolean; }'.
  Type '{ a: number; }' is missing the following properties from type '{ a: number; b: never; c: never; }': b, c

如何实例化Test 类型的对象而不出现错误?我想要一个可以包含字段 abc 的类型(或为空的 {})。

【问题讨论】:

标签: typescript


【解决方案1】:

我找到了解决方案。我需要像这样将Foos 字段设为可选:

已编辑以包含@apokryfos 的建议

interface Foo {
    a: number;
    b: string;
    c: boolean;
}

现在我可以做:

interface Foo {
    a: number;
    b: string;
    c: boolean;
}

type AtMostOneOf<T> = keyof T extends infer K
    ? K extends unknown
    ? { [I in keyof T]+?: I extends K ? T[I] : never }
    : never
    : never;


type Test = AtMostOneOf<Foo>;

const test: Test = {a: 1}; // allowed
const test1: Test = {b: 'asd'}; // allowed
const test2: Test = {a: 1, b: 'asd'}; // not allowed
const test3: Test = {} // allowed

Playground

【讨论】:

  • 您不需要在Foo 中将Foo 属性设为可选。您可以通过[I in keyof T]+?:Explode 类型中制作它们,例如this
【解决方案2】:

您可以将Explode 类型定义为:


type Explode<T> = {
    [K in keyof T]: {
        [key in K]: T[K]
    }
}[keyof T]

那么type Test 将变为:

type Test = {
    a: number;
} | {
    b: string;
} | {
    c: boolean;
}

TS Playground

【讨论】:

  • 谢谢,但我需要一种只允许设置三个字段中的一个(或不设置)的类型。您的示例允许同时设置多个字段,例如const test: Test = { a: 1, b: 'asd' };
猜你喜欢
  • 2023-01-17
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2020-06-10
  • 1970-01-01
  • 2017-03-31
相关资源
最近更新 更多