如何根据类型变量的属性为通用类动态分配类型?例如
interface EntityErrors<T> {
[p in keyof T]?: string; // How can I make "string" dynamic? It needs to be a string for primitives (id, name), and an array of strings for the `teachers` array.
// I've tried the following, but it appears `teachers` is still resolving to `SimpleError` instead of `ArrayOfErrors`.
[p in keyof T]?: p extends [] ? ArrayOfErrors<p> : SimpleErrors;
// I've also tried `instanceof` and `typeof`, but I receive syntax errors.
[p in keyof T]?: p instanceof [] ? ArrayOfErrors<p>: SimpleErrors;
}
interface School {
id: string;
name: string;
teachers: Teacher[];
}
interface Teacher {
id: string;
name: string;
}
因为School
错误对象看起来像:
{
"id": "The input is invalid",
"name": "The input is invalid",
"teachers": [
{
"id": "The input is invalid",
"name": "The input is invalid"
},
{
"id": "The input is invalid",
"name": "The input is invalid"
}
]
}
答案 0 :(得分:2)
p
是带有属性名称的字符串类型。
您需要检查类中属性的类型:
[p in keyof T]?: T[p] extends [] ? ArrayOfErrors<T[p]>: SimpleErrors;
答案 1 :(得分:1)
根据您的要求,事情会变得更加复杂,因为错误类型需要递归。如果遇到原始数组或原始属性,则结果类型中的属性将为字符串。如果我们有一个实体或一个实体数组,我们需要递归地应用类型以获得适当的结果。
为此,我们需要使用映射类型。属性的类型为T[P]
,其中P
为属性名称
type EntityErrors = {
[P in keyof T]?:ErrorProperty<T[P]>
}
type Primitive = number| string| Date | boolean
type ErrorProperty<T> =
T extends Primitive ? string :
T extends Array<Primitive> ? string[] :
T extends Array<infer U> ? Array<EntityErrors<U>> :
EntityErrors<T>;
interface School {
id: string;
name: string;
teachers: Teacher[];
}
interface Teacher {
id: string;
name: string;
}
let e:EntityErrors<School> = {
"id": "The input is invalid",
"name": "The input is invalid",
"teachers": [
{
"id": "The input is invalid",
"name": "The input is invalid"
},
{
"id": "The input is invalid",
"name": "The input is invalid"
}
]
}