简体   繁体   English

TypeScript TupleIndexed 类型并强制对作为参数传入的数组只读

[英]TypeScript TupleIndexed type and enforce read only for arrays passed in as arguments

I want to create type in TypeScript that takes a type parameter T and tuple/ReadonlyArray of keyof T and returns a ReadonlyArray of the keys indexed into T .我想在 TypeScript 中创建type ,它采用类型参数Tkeyof T元组/ReadonlyArray 并返回索引到T的键的 ReadonlyArray 。

type TupleIndexed<T, K extends ReadonlyArray<keyof T>> = {
  [C in keyof K]: T[C];
};

But I get Type 'C' cannot be used to index type 'T' .但是我得到Type 'C' cannot be used to index type 'T'

One workaround I found is我发现的一种解决方法是

type TupleIndexed<T, K extends ReadonlyArray<keyof any>> = {
  [C in keyof K]: K[C] extends keyof T ? T[K[C]] : never;
};

While it gets the job done, I don't understand why the conditional is necessary for the compiler.虽然它完成了工作,但我不明白为什么编译器需要条件。

This way I'm able to write typed functions that preserve the positional type information like the following这样我就可以编写保留位置类型信息的类型化函数,如下所示

function pluck<T, K extends ReadonlyArray<keyof T>>(obj: T, keys: K): TupleIndexed<T, K> {
  return keys.map(key => obj[key]);
}

const vals = pluck({name: 'John', age: 25, adult: true}, [
  'name', 
  'age', 
  'adult'
] as const);
const name = vals[0]; // string
const age = vals[1]; // number
const adult = vals[2]; // boolean
const doesNotExist = vals[3]; // ERROR

However, even in this solution, not casting the array as const still compiles但是,即使在这个解决方案中,不将数组转换as const仍然可以编译

function pluck<T, K extends ReadonlyArray<keyof T>>(obj: T, keys: K): TupleIndexed<T, K> {
  return keys.map(key => obj[key]);
}

const vals = pluck({name: 'John', age: 25, adult: true}, [
  'name', 
  'age', 
  'adult'
]);  // Not explicitly stating as const still compiles
const name = vals[0]; // string | number | boolean
const age = vals[1]; // string | number | boolean
const adult = vals[2]; // string | number | boolean
const doesNotExist = vals[3]; // string | number | boolean

Which loses all the positional type safety.这失去了所有的位置类型安全。 Is there a way to automatically cast the array as const or otherwise have the compiler throw an error when it isn't casted as const ?有没有办法自动将数组转换as const或者当它没有转换as const时,编译器会抛出错误?

Is there a way to automatically cast the array as const or otherwise have the compiler throw an error when it isn't casted as const ?有没有办法自动将数组转换为const或者当它没有转换为const时,编译器会抛出错误?

As far as I know, there is not.据我所知,没有。

However, using a rest parameter instead of an array will result in TypeScript treating it as a tuple instead of an array.但是,使用 rest 参数而不是数组将导致 TypeScript 将其视为元组而不是数组。 Of course this also means have to call it slightly differently:当然,这也意味着必须稍微不同地称呼它:

type TupleIndexed<T, K extends ReadonlyArray<keyof any>> = {
  [C in keyof K]: K[C] extends keyof T ? T[K[C]] : never;
};

function pluck<T, K extends ReadonlyArray<keyof T>>(obj: T, ...keys: K): TupleIndexed<T, K> {
//                                                          ^^^
  return keys.map(key => obj[key]) as any;
}

const vals = pluck({name: 'John', age: 25, adult: true}, 'name', 'age', 'adult');
const name = vals[0]; // string
const age = vals[1]; // number
const adult = vals[2]; // boolean
const doesNotExist = vals[3]; // error

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM