如何强制 class 实现可以存储未定义值的属性
How to force class to implement properties that can store undefined value
我正在尝试创建一个映射类型,它会强制 class 实现一组基于某些对象类型的属性。基本上当扩展对象类型时,class也需要扩展。
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
中的所有对象属性都是可选的 ?
它不会强制 class 实现它们。
我尝试使用 | undefined
但它也不起作用。让它工作的唯一方法是使用 -?
:
摆脱 ?
type SomeMappedType = {
[K in keyof SomeObjectType]-?: SomeGenericClass<K>
}
class SomeClass implements SomeMappedType {
a: SomeGenericClass<'a'>;
b: SomeGenericClass<'b'>;
c: SomeGenericClass<'c'>;
}
但是我无法将 undefined
值存储到这些属性。
Non-optional 属性(没有?)必须定义,但通过类型联合我们可以指定它们是指定类型还是未定义。
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 }
可选属性本质上允许未定义,所以我们实际上不需要联合类型。您可以将 属性 指定为未定义或省略它。
interface OptionalShorthandFoo {
bar?: string
baz?: string
}
const z: OptionalShorthandFoo = { bar: 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
。
我正在尝试创建一个映射类型,它会强制 class 实现一组基于某些对象类型的属性。基本上当扩展对象类型时,class也需要扩展。
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
中的所有对象属性都是可选的 ?
它不会强制 class 实现它们。
我尝试使用 | undefined
但它也不起作用。让它工作的唯一方法是使用 -?
:
?
type SomeMappedType = {
[K in keyof SomeObjectType]-?: SomeGenericClass<K>
}
class SomeClass implements SomeMappedType {
a: SomeGenericClass<'a'>;
b: SomeGenericClass<'b'>;
c: SomeGenericClass<'c'>;
}
但是我无法将 undefined
值存储到这些属性。
Non-optional 属性(没有?)必须定义,但通过类型联合我们可以指定它们是指定类型还是未定义。
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 }
可选属性本质上允许未定义,所以我们实际上不需要联合类型。您可以将 属性 指定为未定义或省略它。
interface OptionalShorthandFoo {
bar?: string
baz?: string
}
const z: OptionalShorthandFoo = { bar: 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
。