我正在尝试创建一个映射类型,它将强制类实现一组基于某些对象类型的属性。基本上,当对象类型被扩展时,类也需要被扩展。
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 }
操场上联系