嗨,我对typescript很陌生,我想键入一个包含按类别分组的数组的对象,我想根据这个键入。
const machines:IMachines = {
1: [{category:"core", serial:"110"}, {category:"core",serial:231}],
2: [{category:"style", serial:"114"}, {category:"style",serial:"239"}]
}
type IMachines = {
[key:number]:IMachine[]
}
type IMachine = {
category:string
serial: string
}
从这里开始,我想缩小类型,以确保同一数组中的所有机器都具有相同的"类别"。类型。
例如,如果我改变机器对象,使序列号为239的机器现在类型为&;core&;。这应该会抛出TS错误,因为style和core在同一个数组中是不同的分类类型。
const machines:IMachines = {
1: [{category:"core", serial:"110"}, {category:"core",serial:231}],
2: [{category:"style", serial:"114"}, {category:"core",serial:"239"}]
}
==>这会抛出错误
我不知道该怎么做:
我会尝试这样做:
type IMachines<T> = {
[key:number]:IMachine<T>[]
}
type IMachine<T> = {
category:TCategory<T>
serial: string
}
type TCategory<K> = K
这不起作用,但是,我张贴只是为了解释我想要实现的想法。
Thank you very much
这是个有趣的问题。TypeScripts独立类型不能验证像这样的复杂约束。使用泛型可以实现这一点,但您必须显式地为泛型类型提供有效的category
名称列表。
也可以用泛型函数验证这样的对象。一个可能的实现是这样的:
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type NoUnion<Key> =
[Key] extends [UnionToIntersection<Key>] ? Key : never;
function validateMachines<
T extends Record<string, string>
>(machines: { [K in keyof T]: { category: NoUnion<T[K]>, serial: string }[] }) {
return machines
}
如果你用你的machines对象调用这个,它们将被正确地验证。
const res1 = validateMachines({
1: [{category:"core", serial:"110"}, {category:"core",serial:"231"}],
2: [{category:"style", serial:"114"}, {category:"style",serial:"239"}]
})
const res2 = validateMachines({
1: [{category:"core", serial:"110"}, {category:"core",serial:"231"}],
2: [{category:"style", serial:"114"}, {category:"core",serial:"239"}] // Error
})
游乐场
如果您有一个预定义的enum
,解决方案看起来像这样:
enum Categories {
core = "core",
style = "style"
}
type IMachines = Record<number, {
-readonly [K in keyof typeof Categories]: { category: K, serial: string }[]
}[keyof typeof Categories]>
const machines: IMachines = {
1: [{category:"core", serial:"110"}, {category:"core",serial:"231"}],
2: [{category:"style", serial:"114"}, {category:"core",serial:"239"}]
// ^Error
}
游乐场