在功能打字稿自动捕获阵列型可变

问题描述 投票:0回答:2

我尝试代码:

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(...)按预期工作?

typescript generics type-inference
2个回答
0
投票

我相信这里的问题是,['a', 'b']实际上是由打字稿类型为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

打字稿不会自动推断数组常量元组的,可能会导致一些问题 - 看this issue的多一点背景。

在你的情况,你通过期望它应该工作:

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

// or
const value: ['a', 'b'] = ['a', 'b']
nth(value, 1)

0
投票

我建议为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);

Playground

这是您所期望的行为?

---编辑---

如果你想获得“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'
© www.soinside.com 2019 - 2024. All rights reserved.