打字稿接口:可选但并非未定义

Kim*_*jun 11 typescript

我该如何描述类型

key 是可选的,但如果它存在,则不能取消定义。

第一次,我使用 Partial 使 T 的所有属性都是可选的。

interface A {
  a: number;
}

var data: A = {
  a: 1,
}

var update1: Partial<A> = {

}

var update2: Partial<A> = {
  a: undefined
}

var result1: A = {
  ...data,
  ...update1,
} // { a: 1 }

var result2: A = {
  ...data,
  ...update2,
} // { a: undefined }
Run Code Online (Sandbox Code Playgroud)

这里的问题是 result2 没有在运行时实现接口 A,但 typescript 从不抱怨它。它是错误还是功能?我猜打字稿不能很好地与传播运算符一起工作......

目标是使用打字稿区分这两个变量!


var data: T = {
  a: 1,
  b: 2,
}

var optional1: MyPartial<T> = { // Totally OK

}

var optional2: MyPartial<T> = { // OK
  a: 3,
}

var optional3: MyPartial<T> = { // OK
  b: 4,
}

var optional4: MyPartial<T> = { // OK
  a: 3,
  b: 4,
}

var undef1: MyPartial<T> = { // typescript must throw error
  a: undefined,
}

var undef2: MyPartial<T> = { // typescript must throw error
  a: 3,
  b: undefined
}

...

Run Code Online (Sandbox Code Playgroud)

看看这个TypeScript 游乐场示例。

cdo*_*orn 9

现在 4.4.0 中存在支持,通过--exactOptionalPropertyTypes

\n
\n

因此,默认情况下,TypeScript 不会\xe2\x80\x99 区分值未定义的当前属性和缺失的属性...

\n

在 TypeScript 4.4 中,新标志 --exactOptionalPropertyTypes 指定\n可选属性类型应完全按照书面形式进行解释,\n这意味着 | undefined 不会添加到类型中:

\n
\n

https://devblogs.microsoft.com/typescript/announcing-typescript-4-4/#exact-optional-property-types

\n


Dmi*_*riy 4

正如 @dtanabe 提到的,在 TypeScript 支持之前(如果他们决定这样做的话),这里并没有真正好的解决方案。在用户态执行此操作的主要问题是,在 var def (即const x: Foo = ...)中,我们无权访问该值的类型。如果您可以将代码从使用扩展更改为使用函数,您可以执行以下操作:

interface A {
  a: number;
}

type EnsurePartial<TTarget, TUpdate extends keyof TTarget> =
  undefined extends TTarget[TUpdate]
  ? never
  : { [Key in TUpdate]: TTarget[Key] };

declare function update<T>(propsToUpdate: EnsurePartial<A, T>): void

update({}) // OK
update({ a: 42 }) // OK
update({ a: undefined }) // error
update({ c: undefined }) // error
Run Code Online (Sandbox Code Playgroud)