如何使用按类别分组的数组缩小对象的类型,当每个数组中的所有项必须具有相同的类别类型时

  • 本文关键字:类型 数组 何使用 缩小 对象 typescript
  • 更新时间 :
  • 英文 :


嗨,我对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
}

游乐场

相关内容

  • 没有找到相关文章

最新更新