Typescript:从数组类型检索元素类型信息

r7s23pms  于 2022-12-05  发布在  TypeScript
关注(0)|答案(8)|浏览(189)

假设我有一个T[]类型的数组,是否可以在另一个别名/接口中提取T类型?例如,我的(伪)理想代码如下:

// for illustration only...

type ArrayElement<T[]> = T;

// then, ArrayElement<string[]> === string

如果不是,有没有一般的类型理论理由不允许这样的算子?如果还是不是,我可能建议添加它。
谢谢你!

htrmnn0y

htrmnn0y1#

更新:基于下面@耶里科的回答

下列型别别名会传回数组或Tuple中元素的型别:

type ArrayElement<ArrayType extends readonly unknown[]> = 
  ArrayType extends readonly (infer ElementType)[] ? ElementType : never;

下面这些例子是可行的:

type A = ArrayElement<string[]>; // string
type B = ArrayElement<readonly string[]>; // string
type C = ArrayElement<[string, number]>; // string | number
type D = ArrayElement<["foo", "bar"]>; // "foo" | "bar"
type E = ArrayElement<(P | (Q | R))[]>; // P | Q | R

type Error1 = ArrayElement<{ name: string }>; 
//                         ^^^^^^^^^^^^^^^^
// Error: Type '{ name: string; }' does not satisfy the constraint 'readonly unknown[]'.

说明

类型保护(尖括号中的位)ArrayType extends readonly unknown[]表示,我们希望类型参数ArrayType至少是一个只读数组(它也接受可变数组),这样我们就可以查看它的元素类型。
这样可以防止传入非数组值,如最后一个示例所示,这样可以防止ArrayElement返回never
注意,readonly unknown[]是TypeScript 3.4中添加的语法;对于早期版本,请使用ReadonlyArray<unknown>
在右边,条件表达式要求编译器在模式readonly ElementType[]中填充ElementType的值,如果可以,则返回ElementType,如果不能,则返回never
由于开头的类型保护意味着我们只会被传递一个与此模式匹配的值,因此它可以保证总是匹配,并且永远不会返回never

上一个答案

type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType[number];
xbp102n0

xbp102n02#

从2.1开始,typescript支持类型的[ ]运算符。正式名称是索引访问类型,也称为查找类型,它的工作方式如下:

type A = {a: string, b: number} [];

type AElement = A[0];

let e: AElement = {x: 0}; //error TS2322: Type '{ x: number; }' is not 
                       //assignable to type '{ a: string; b: number; }'
u91tlkcl

u91tlkcl3#

另一种选择:

type ArrayElement<A> = A extends readonly (infer T)[] ? T : never
x6h2sr28

x6h2sr284#

这可以通过在括号中写入索引类型很容易地实现:

type ArrayElementType = ArrayType[number];

更新

正如下面的注解所建议的,创建一个泛型数组元素类型:

type ArrayElementType<ArrayType extends Array> = ArrayType[number];
  • P.S. number不是一个值,而是一个类型。*
ltqd579y

ltqd579y5#

实用程序类型库具有该www.example.com的类型https://github.com/piotrwitek/utility-types#valuestypet(沿着许多其他类型)
比如说

import { ValuesType } from 'utility-types';

type NumberArray = number[];
// Expect: number
type NumberItems = ValuesType<NumberArray>;
dohp0rv5

dohp0rv56#

另一个选项:

type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;

有关infer的更多信息,请访问:https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#inferring-within-conditional-types:

6ioyuze2

6ioyuze27#

我得到了最短的答案。

type A = Array<string>;
type B = A[0]; // string

https://www.typescriptlang.org/play?ssl=2&ssc=15&pln=1&pc=1#code/C4TwDgpgBAglC8sBOSCGIA8BnYSCWAdgOYB8A3AFCiRQBCCsA2gAwC6ZQA

ct3nt3jp

ct3nt3jp8#

根据@will-madem的回答,我做了一些调整:

  • 泛型可以是数组,也可以不是:TT[]
  • 它将删除阵列的多个“级别”:T[][][] =〉T

此处为完整示例。

type ArrayElement<MaybeArrayType> = 
  MaybeArrayType extends readonly (infer ElementType)[]
    ? (
        ElementType extends unknown[]
            ? ArrayElement<ElementType>
            : ElementType
    )
    : MaybeArrayType;

相关问题