我有一个这样的方法:
public select(fieldName: keyof TType)
Run Code Online (Sandbox Code Playgroud)
哪里TType可以是数组类型。在数组类型的情况下,fieldName将正确地为我提供 type 的所有属性名称Array。
如果我使用一种类型调用此方法,User[]我想获取 的属性User而不是 的属性Array。
有没有办法做到这一点?
额外问题:有没有办法限制 TType 为数组类型?
jca*_*alz 18
您绝对可以制作一个条件类型函数,将数组类型解包至一层深度,然后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
Run Code Online (Sandbox Code Playgroud)
对于打字,我认为这应该可以正常工作。显然,您还需要有一个有效的实现(并注意,实现中的条件类型通常需要一些类型断言或重载才能使编译器满意……但您似乎问的是类型,而不是实现)。
至于您的额外问题,是的,您可以限制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
Run Code Online (Sandbox Code Playgroud)
请注意,我在这里完全取消了条件类型,因为它更直接。
希望有所帮助;祝你好运!
Kar*_*ski 10
您将需要一个小帮手来提取盒装类型:
type Unboxed<T> =
T extends (infer U)[]
? U
: T;
Run Code Online (Sandbox Code Playgroud)
那么你的方法可以如下所示:
interface User {
id: symbol;
name: string;
}
class Foo {
select(fieldName: keyof Unboxed<User[]>) {
console.log(fieldName) // "id" | "name"
}
}
Run Code Online (Sandbox Code Playgroud)
至于你的额外问题:是的,有可能,但可能感觉有点奇怪。
class Foo {
select<T extends any[]>(fieldName: keyof Unboxed<T>) {
console.log(fieldName)
}
}
new Foo()
.select<Window[]>('addEventListener')
Run Code Online (Sandbox Code Playgroud)
类型参数旨在描述方法内部的参数或类的泛型类型。所以也许您想要执行以下操作:
class Foo<T extends any[]> {
select(fieldName: keyof Unboxed<T>) {
console.log(fieldName)
}
}
new Foo<Window[]>()
.select('addEventListener')
Run Code Online (Sandbox Code Playgroud)