如何强制类实现可以存储未定义值的属性



我正在尝试创建一个映射类型,它将强制类实现一组基于某些对象类型的属性。基本上,当对象类型被扩展时,类也需要被扩展。

type SomeObjectType = {
    a?: {/* ... */},
    b?: {/* ... */},
    c?: {/* ... */}
}
type SomeMappedType = {
    [K in keyof SomeObjectType]: SomeGenericClass<K>
}
class SomeClass implements SomeMappedType {
  a?: SomeGenericClass<'a'>;
  b?: SomeGenericClass<'b'>;
  c?: SomeGenericClass<'c'>;
}

上面代码的问题是,因为SomeObjectType中的所有对象属性都是可选的,所以?并没有强制类实现它们。

我试图使用| undefined,但它也不起作用。使其工作的唯一方法是使用-?:

去除?
type SomeMappedType = {
    [K in keyof SomeObjectType]-?: SomeGenericClass<K>
}
class SomeClass implements SomeMappedType {
  a: SomeGenericClass<'a'>;
  b: SomeGenericClass<'b'>;
  c: SomeGenericClass<'c'>;
}

但是我不能将undefined值存储到这些属性中。

这是你需要的吗?我使用Array是为了演示。

type SomeObjectType = {
a: {/* ... */},
b?: {/* ... */},
c?: {/* ... */}
}
type RequiredLiteralKeys<T> = keyof { [K in keyof T as string extends K ? never : number extends K ? never :
{} extends Pick<T, K> ? never : K]: 0 }
type OptionalLiteralKeys<T> = keyof { [K in keyof T as string extends K ? never : number extends K ? never :
{} extends Pick<T, K> ? K : never]: 0 }
type SomeMappedType = {
[K in RequiredLiteralKeys<SomeObjectType>]: Array<K>
} & {
[K in OptionalLiteralKeys<SomeObjectType>]-?: Array<K> | undefined
}
class SomeClass implements SomeMappedType {
a!: Array<'a'>;
b!: Array<'b'>;
c!: undefined // will error if c is missing but undefined still works
}

所有必需属性保留为必需属性,所有可选属性将转换为Array<T> | undefined

游乐场

必须定义非可选属性(no ?),但通过类型联合可以指定它们是指定类型或未定义。

interface MandatoryFoo {
bar: string | undefined
baz: string | undefined
}
const x: MandatoryFoo = { bar: undefined, baz: undefined }

可选属性(带?)可以省略。

interface OptionalFoo {
bar?: string | undefined
baz?: string | undefined
}
const y: OptionalFoo = { bar: undefined }

可选属性本质上允许未定义,因此我们实际上不需要union类型。您可以指定该属性为未定义或忽略它。

interface OptionalShorthandFoo {
bar?: string
baz?: string
}
const z: OptionalShorthandFoo = { bar: undefined }

操场上联系

最新更新