[英]How to get Type of Array in Typescript generics
我有一个这样的方法:
public select(fieldName: keyof TType)
其中TType
可以是数组类型。 在数组类型的情况下, fieldName
将正确地为我提供Array
类型的所有属性名称。
如果我User[]
类型调用此方法,我想访问User
的属性而不是Array
的属性。
有没有办法做到这一点?
额外问题:有没有办法限制 TType 为数组类型?
您绝对可以创建一个条件类型函数,将数组类型解包至一层深度,然后对结果使用keyof
。 例如:
// unwrap up to one level
type Unarray<T> = T extends Array<infer U> ? U : T;
// your class maybe
declare class Thingy<T> {
constructor(t: T);
public select(fieldName: keyof Unarray<T>): void;
}
// your interface maybe
interface User {
name: string,
age: number
}
declare const u1: User;
declare const u2: User;
const x = new Thingy(u1);
x.select("name"); // okay
const y = new Thingy([u1, u2]);
y.select("age"); // okay
y.select("push"); // error
对于打字,我认为这应该可以正常工作。 显然,您还需要有一个有效的实现(并注意,实现中的条件类型通常需要一些类型断言或重载才能使编译器满意……但您似乎问的是类型,而不是实现)。
至于您的额外问题,是的,您可以将T
限制为仅数组类型,如下所示:
// your class maybe
declare class Thingy<T extends Array<any>> {
constructor(t: T);
public select(fieldName: keyof (T[number])): void;
}
// your interface maybe
interface User {
name: string,
age: number
}
declare const u1: User;
declare const u2: User;
const x = new Thingy(u1); // error
const y = new Thingy([u1, u2]);
y.select("age"); // okay
请注意,我在这里完全取消了条件类型,因为它更直接。
希望有所帮助; 祝你好运!
您将需要一个小助手来提取盒装类型:
type Unboxed<T> =
T extends (infer U)[]
? U
: T;
那么你的方法可以是这样的:
interface User {
id: symbol;
name: string;
}
class Foo {
select(fieldName: keyof Unboxed<User[]>) {
console.log(fieldName) // "id" | "name"
}
}
至于你的额外问题:是的,这是可能的,但可能感觉有点奇怪。
class Foo {
select<T extends any[]>(fieldName: keyof Unboxed<T>) {
console.log(fieldName)
}
}
new Foo()
.select<Window[]>('addEventListener')
类型参数旨在描述方法或类的泛型类型中的参数。 因此,也许您想要执行以下操作:
class Foo<T extends any[]> {
select(fieldName: keyof Unboxed<T>) {
console.log(fieldName)
}
}
new Foo<Window[]>()
.select('addEventListener')
可以通过按数字索引来从类型type U = T[]
的数组中确定类型参数T
,例如U[number]
。
type Foo = {"foo": string};
type Bar = {"bar": number};
type FooArray = Foo[];
type BarArray = Bar[];
FooArray[number]; // {"foo": string}
BarArray[number]; // {"bar": number}
这是带有上述示例的TypeScript Playground 。
为什么要使用运算符keyof
? 在每种情况下都会导致一个数组,因为 fieldName 将只是TType
类型中的键。
如果你想要一个User
数组,你需要这样定义TType
:
type TType = User[]
...
public select(fieldName: TType) {
...
}
如果你希望TType
是任何数组,你将把它定义为这样的类型 TType = any[]
但是在第二个定义中,打字稿将无法推断内部类型(在这种情况下,我认为User
不是您想要的类型。
最后,如果TType
可以是多种类型的数组:type TType = User[] | 随便[] | ...
如果您想要更详细的答案,请对您想要的内容提供更好的解释。
与此同时,我希望这会有所帮助;)
塞伯
使用TType[0]
作为类型在实践中对我TType[0]
。 所以,在你的例子中:
public select(fieldName: keyof TType[0])
尽管它很丑,但它似乎有效!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.