Jos*_*des 2 javascript types typescript
我想知道是否可以在打字稿中键入对象中动态属性的最大数量。
所以基本的例子是跟踪事件:
events.track('SOME_EVENT', { first: 'a', other: 'b', some: 'c'})
Run Code Online (Sandbox Code Playgroud)
事件数据应该最多保存 3 个属性及其各自的值,键也可以是动态的。
我用 basic 键入它Record,但允许的属性数量没有限制:
export interface Events {
track: (name: string, params?: Record<string, string | number | unknown>) => void;
}
Run Code Online (Sandbox Code Playgroud)
这可能吗?
TuplifyUnion我从这里得到了一个解决方案:
我不确定这有多“安全”(请参阅免责声明)。使用TuplifyUnion被认为是不安全的,因为订单可能随时更改。由于这里的顺序并不重要,在这种情况下只有元素的数量很重要,所以我认为在这里使用这是可以的。
该解决方案允许 0-3 个键。如果您想要任何其他金额,只需将它们添加到联合中(例如1 | 2接受 1 或 2 个键)。
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type LastOf<T> =
UnionToIntersection<T extends any ? () => T : never> extends () => (infer R) ? R : never
type Push<T extends any[], V> = [...T, V];
type TuplifyUnion<T, L = LastOf<T>, N = [T] extends [never] ? true : false> =
true extends N ? [] : Push<TuplifyUnion<Exclude<T, L>>, L>
type MaxThreeProperties<T extends Record<string, any>> =
TuplifyUnion<keyof T>["length"] extends 0 | 1 | 2 | 3 ? T : never
// add all acceptable key amounts here ^ ^ ^ ^
function track<T extends Record<string, any>>(
name: string,
params: MaxThreeProperties<T>
) {}
Run Code Online (Sandbox Code Playgroud)
我们基本上将所有键放入一个元组中,然后“手动”检查元组的长度。这可以很容易地扩展到其他数量的属性,尽管它可能会变得丑陋。
一个缺点是错误消息:
类型“string”不可分配给类型“never”。(2322)
这对于使用该功能的人来说可能会感到困惑......
以下是一些测试:
track('SOME_EVENT', {}) // works
track('SOME_EVENT', {a: ""}) // works
track('SOME_EVENT', {a: "", b: ""}) // works
track('SOME_EVENT', {a: "", b: "", c: ""}) // works
track('SOME_EVENT', {a: "", b: "", c: "", d: ""}) // ERROR
track('SOME_EVENT', {a: "", b: "", c: "", d: "", e: ""}) // ERROR
const a = {a: "", b: "", c: ""}
const b = {a: "", b: "", c: "", d: ""}
track('SOME_EVENT', a) // works
track('SOME_EVENT', b) // ERROR
Run Code Online (Sandbox Code Playgroud)