TypeScript:如何在输入中应用地图功能?

时间:2019-03-05 10:51:32

标签: typescript typing

目前,我有以下几种类型:

type Value = boolean | number | string

class Struct<T extends Value[] = Value[]> {

    constructor(fmt: string) { }

    pack(...args: T): Buffer { }

}

我想知道如何用由以下代码段传递给构造函数的每个<???>使用的Value[]的列表替换Struct

class StructConcat<T extends Struct[]> {

    constructor(...structs: T) { }

    pack(...args_list: <???>) { }

}

// example:
const a: HeadStruct = new Struct<[number]>('<I')
const b: VectorStruct = new Struct<[number, number, number]>('<3f')
const concat = new StructConcat(a, b)

最终,StructConcat.pack函数应受以下约束:

concat.pack([1], [2, 3, 4])

到目前为止,我能做的最好的事情是:(T[number] extends Struct<infer K> ? K : never)[],但在上述情况下,它输出的([number] | [number, number, number])[]接近,但仍然没有:[[number], [number, number, number]]

TypeScript的打字系统允许这种事情吗?

1 个答案:

答案 0 :(得分:1)

您可以在3.1开始的映射类型中使用元组:

type Value = boolean | number | string

class Struct<T extends Value[] = Value[]> {

    constructor(fmt: string) { }

    pack(...args: T): Buffer { }

}

type ExtractValueFromStruct<T> = T extends Struct<infer V> ? V : never
type MapStructTuple<T extends Struct[]> = { 
    [P in keyof T]: ExtractValueFromStruct<T[P]>
}

class StructConcat<T extends Struct[]> {

    constructor(...structs: T) { }

    pack(...args_list: MapStructTuple<T>) { }

}

// example:
const a= new Struct<[number]>('<I')
const b= new Struct<[number, number, number]>('<3f')
const concat = new StructConcat(a, b)
concat.pack([1], [1, 2, 3])
concat.pack([1], [1, 2, 3, 4]) // err