TypeScript: как применить функцию map к наборам?

#typescript #typing

#typescript #ввод

Вопрос:

В настоящее время у меня есть несколько следующих типов:

 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:

Вы можете использовать кортежи в сопоставленных типах, начиная с версии 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
  

Комментарии:

1. @WKnight02 рад помочь 🙂