我有一个对象类型,该对象类型使用一个枚举中的所有键都声明为字符串:
enum MyProperties {
PROP_A = 'propA',
PROP_B = 'propB',
PROP_C = 'propC'
}
type Foo {
[value in MyProperties]: string;
}
如何在将Foo
中的属性之一声明为数字的同时仍确保其所有键都在MyProperties
中?
即
type Foo {
propA: string;
propB: string;
propC: number;
}
答案 0 :(得分:1)
就这么简单
export type Foo {
[value in keyof typeof MyProperties]: string;
}
答案 1 :(得分:1)
如果您希望将特定属性键入为数字,则可以执行以下操作:
type Foo<T extends MyProperties> = {
[value in MyProperties]: T extends value ? number : string;
}
或者您可以使用更通用的解决方案:
enum MyProperties {
PROP_A = 'propA',
PROP_B = 'propB',
PROP_C = 'propC'
}
type OneOf<T extends {
[key: string]: any;
}, R, P extends keyof T = keyof T> = P extends keyof T ? {
[K in P]: R;
} & {
[K in keyof Omit<T, P>]: T[K];
} : never
type Foo = OneOf<{
[value in MyProperties]: string;
}, number>
const k: Foo = {
propA: "",
propB: 3,
propC: "",
}
答案 2 :(得分:1)
决定继续使用:
enum MyProperties {
PROP_A = 'propA',
PROP_B = 'propB',
PROP_C = 'propC'
}
type Foo {
[MyProperties.PROP_A]: string;
[MyProperties.PROP_B]: string;
[MyProperties.PROP_C]: number;
}
希望找到一种既简单又简单的方法来做到这一点。但是,由于只有这么少的一组属性,看起来很明确。
答案 3 :(得分:0)
您要为一个对象定义一个类型,该对象的键与枚举中的每个值匹配,并且值不同(在示例中为string
和number
)。您要强制每个键都匹配适当的值,同时还要求所有键都具有某个值。
这可能有点令人困惑,因为我们试图在 type 而不是对象上强制键入。但是我们可以做一些事情。
type NumberProperties = MyProperties.PROP_C;
type StringProperties = Exclude<MyProperties, NumberProperties>
type Foo = {
[K in NumberProperties]: number;
} & {
[K in StringProperties]: string;
}
MissingKeys
来检查编译时是否没有忘记任何内容。我们确实需要自己检查它,因为不会引发任何错误。enum MyProperties {
PROP_A = 'propA',
PROP_B = 'propB',
PROP_C = 'propC'
}
type Foo = {
[MyProperties.PROP_B]: string;
[MyProperties.PROP_C]: number;
}
type MissingKeys = Exclude<MyProperties, keyof Foo> // evaluates to MyProperties.PROP_A
Foo
的对象中设置所有缺少的属性。让我们给它一个不合逻辑的值,以便我们可以注意到Foo
中缺少某些内容,并相应地调整了Foo
。我喜欢这一行,因为我们得到了一个大的红色下划线,因此很明显该类型是错误的。type DefinedFoo = {
[MyProperties.PROP_B]: string;
[MyProperties.PROP_C]: number;
}
type MissingKeys = Exclude<MyProperties, keyof DefinedFoo> // evaluates to MyProperties.PROP_A
type Foo = DefinedFoo & {
[K in MissingKeys]-?: "missing property definition"
}
const fooImplementation1: Foo = {
[MyProperties.PROP_B]: "b",
[MyProperties.PROP_C]: 0,
}
// gives an error: Property 'propA' is missing...
const fooImplementation2: Foo = {
[MyProperties.PROP_A]: "a",
[MyProperties.PROP_B]: "b",
[MyProperties.PROP_C]: 0,
}
// gives an error: Type of computed property's value is '"a"', which is not assignable to type '"missing property definition"'