TypeScript переменная типа автоматического захвата массива в функции - PullRequest
0 голосов
/ 10 февраля 2019

Я пробовал код:

nth(['a', 'b'], 1) // function nth<string[], 1>(o: string[], k: 1): string
nth<['a', 'b']>(['a', 'b'], 1) // function nth<["a", "b"], number | "0" | "1" | "length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | ... 14 more ... | "values">(o: [...], k: number | ... 30 more ... | "values"): "a" | ... 29 more ... | (() => IterableIterator<...>)
nth<['a', 'b'], 1>(['a', 'b'], 1) // function nth<["a", "b"], 1>(o: ["a", "b"], k: 1): "b"

function nth<O, K extends keyof O>(o: O, k: K): O[K] {
  return o[k]
}

nth<['a', 'b'], 1>(...) работает хорошо, но есть ли способ заставить nth(...) работать как положено?

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Я считаю, что проблема в том, что ['a', 'b'] на самом деле набирается TypeScript как string[], поэтому доступ к элементу в этом массиве даст вам string.Концептуально вы хотите, чтобы ['a', 'b'] был напечатан как кортеж.Например:

const array = ['a', 'b']
const str = array[1] // this is typed as string

const tuple: ['a', 'b'] = ['a', 'b']
const b = tuple[1]   // this is typed as 'b'

Playground

TypeScript не автоматически выводит литералы массива в виде кортежей, поскольку это может вызвать некоторые проблемы - см. эту проблему немного больше контекста.

В вашем случае все должно работать так, как вы ожидаете, через:

nth(['a', 'b'] as ['a', 'b'], 1)

// or
const value: ['a', 'b'] = ['a', 'b']
nth(value, 1)
0 голосов
/ 10 февраля 2019

Я предлагаю создать универсальный тип для nth и применить его к определению типа функции.Пример:

type Nth<A extends any[], I extends number> = A[I];

type R = Nth<[1, 2, 3], 1>

function nth<A extends any[], I extends number>(o: A, k: I): Nth<A, I> {
  return o[k]
}

let result = nth(['a', 'b'], 1)
let result1 = nth<['a', 'b'], 1>(['a', 'b'], 1)
let result2 = nth<['a', 'b'], 1>(['a', 'b'], 1);

Детская площадка

Вы ожидаете такого поведения?

--- Отредактировано ---

ЕслиВы хотите получить «b» вместо строки, вы можете сделать что-то вроде этого:

type Nth<A extends string[], I extends number> = A[I];
let result = nth(['a', 'b'], 1) // string 
let result = nth(['a', 'b'] as ['a', 'b'], 1) // string 
let result1 = nth<['a', 'b'], 1>(['a', 'b'], 1) // 'b'
let result2 = nth<['a', 'b'], 1>(['a', 'b'], 1); // 'b'
...