基于是否传递泛型类型的可选属性

Wen*_* Du 4 typescript typescript-generics conditional-types

如何创建一个接口,以便在T传递时a键入T,而在未传递时a可以是可选的(缺少属性),例如:

interface A<T = void> {
  a: T
}

const a1: A<string> = { a: 'a' } //  No error, good

const a2: A = {}

//  Should not throw
// "Property 'a' is missing in type '{}' but required in type 'A<void>'.ts(2741)"
Run Code Online (Sandbox Code Playgroud)

以下方法的唯一问题是a不能从对象中遗漏:

interface A<T = void> {
  a: T extends void ? undefined : T
}

const a3: A = {}

//  TS throws
// "Property 'a' is missing in type '{}' but required in type 'A<void>'. ts(2741)"
Run Code Online (Sandbox Code Playgroud)

Jea*_*let 5

为什么不将 设为undefined默认类型T

\n

否则,您可以使用条件类型:

\n
interface A<T = void> {\n    a: T extends void ? undefined : T\n}\n
Run Code Online (Sandbox Code Playgroud)\n

为了避免所需属性的类型未定义并完全删除该属性,请尝试使用类型:

\n
type A<T = void> = T extends void ? Record<string, never> : { a: T }\n
Run Code Online (Sandbox Code Playgroud)\n

... whereRecord<string, never>是表示空对象的一种奇特方式(不要使用{},这意味着 \xe2\x80\x9cany 非空值\xe2\x80\x9d,因此也接受例如字符串)。如果您还需要除了 之外始终存在的其他属性a,您可以编写如下内容:

\n
type A<T = void> = T extends void ? Record<string, never> : { a: T } & { b: number }\n                                                                     ^^^^^^^^^^^^^^^\n
Run Code Online (Sandbox Code Playgroud)\n