Javascript Typescript-如何基于另一个属性有条件地定义类型
我试图根据同一类型中的静态值有条件地设置函数的返回类型 给定以下代码,是否可以像我在注释中指定的那样进行类型检查 IE,如果Javascript Typescript-如何基于另一个属性有条件地定义类型,javascript,typescript,ecmascript-6,Javascript,Typescript,Ecmascript 6,我试图根据同一类型中的静态值有条件地设置函数的返回类型 给定以下代码,是否可以像我在注释中指定的那样进行类型检查 IE,如果const taskX:Task具有id:'get name',我如何使其如此taskX.run()应根据定义为输出['get-name']的类型返回 类型输出={ “获取名称”:{ 名称:字符串; }; “变老”:{ 年龄:人数; }; “获取喜爱的水果”:(“苹果”、“草莓”、“甜瓜”)[]; }; 类型任务={ //这应该始终是“输出”中定义的静态属性` id:输出的
const taskX:Task
具有id:'get name'
,我如何使其如此taskX.run()
应根据定义为输出['get-name']的类型返回
类型输出={
“获取名称”:{
名称:字符串;
};
“变老”:{
年龄:人数;
};
“获取喜爱的水果”:(“苹果”、“草莓”、“甜瓜”)[];
};
类型任务={
//这应该始终是“输出”中定义的静态属性`
id:输出的关键点;
//如何将此设置为条件并基于'id'从'Outputs'返回类型`
跑步:()=>从不;
};
const taskOne:任务={
id:“获取名称”,
//这应该是有效的
运行:()=>{
返回{name:“弗兰肯斯坦”};
},
};
常量任务二:任务={
id:“获得年龄”,
//这也应该是有效的
运行:()=>{
返回{年龄:22};
},
};
常量任务三:任务={
id:“获取喜爱的水果”,
//这应该以失败告终
//类型“(“苹果”|“香蕉”)[]”不可分配给类型
//“(“苹果”、“草莓”、“甜瓜”)[……”
运行:()=>{
退货[“苹果”、“香蕉”];
},
};
您可以通过声明一个类型来实现这一点,该类型是其中的一个,并且编译器可以根据id判断它是其中的一个
type GetNameTask = {
id: "get-name";
run: () => {name: string};
}
type GetAgeTask = {
id: "get-age";
run: () => {number: string};
}
type GetFavoriteFruitsTask = {
id: "get-favourite-fruits"
run: () => ("apple" | "strawberry" | "melon")[];
}
type Task = GetNameTask | GetAgeTask | GetFavoriteFruitsTask
要了解有关清洁systax的更多信息,您还可以尝试以下方法:
type GenericTask<TId, TOutput> = {
id: TId;
run: () => TOutput
}
type GetNameTask2 = GenericTask<"get-name", {name: string}>
type GetAgeTask2 = GenericTask<"get-age", {age: number}>
type GetFavoriteFruitsTask2 = GenericTask<"get-favourite-fruits", ("apple" | "strawberry" | "melon")[]>
type Task = GetNameTask2 | GetAgeTask2 | GetFavoriteFruitsTask2
类型GenericTask={
工业贸易署;;
运行:()=>TOutput
}
键入GetNameTask2=GenericTask
键入GetAgeTask2=GenericTask
键入getFavoriteFruchtask2=generictTask
类型Task=GetNameTask2 | GetAgeTask2 | GetFavoriteFruitsTask2
您可以通过声明一个类型来实现这一点,该类型是其中的一个,并且编译器可以根据id判断它是其中的一个
type GetNameTask = {
id: "get-name";
run: () => {name: string};
}
type GetAgeTask = {
id: "get-age";
run: () => {number: string};
}
type GetFavoriteFruitsTask = {
id: "get-favourite-fruits"
run: () => ("apple" | "strawberry" | "melon")[];
}
type Task = GetNameTask | GetAgeTask | GetFavoriteFruitsTask
要了解有关清洁systax的更多信息,您还可以尝试以下方法:
type GenericTask<TId, TOutput> = {
id: TId;
run: () => TOutput
}
type GetNameTask2 = GenericTask<"get-name", {name: string}>
type GetAgeTask2 = GenericTask<"get-age", {age: number}>
type GetFavoriteFruitsTask2 = GenericTask<"get-favourite-fruits", ("apple" | "strawberry" | "melon")[]>
type Task = GetNameTask2 | GetAgeTask2 | GetFavoriteFruitsTask2
类型GenericTask={
工业贸易署;;
运行:()=>TOutput
}
键入GetNameTask2=GenericTask
键入GetAgeTask2=GenericTask
键入getFavoriteFruchtask2=generictTask
类型Task=GetNameTask2 | GetAgeTask2 | GetFavoriteFruitsTask2
您希望任务
成为id
和运行
的三种不同可能配对中的一种。您可以通过编程方式从Outputs
的每个Outputs
属性生成与此配对对应的值,然后通过所有映射属性获得所需的并集:
type Task = {
[K in keyof Outputs]: { id: K, run: () => Outputs[K] }
}[keyof Outputs];
/* produces
type Task = {
id: "get-name";
run: () => {
name: string;
};
} | {
id: "get-age";
run: () => {
age: number;
};
} | {
id: "get-favourite-fruits";
run: () => ("apple" | "strawberry" | "melon")[];
}*/
然后,代码的其余部分按需要工作。接受有效的任务:
const taskOne: Task = {
id: "get-name",
run: () => {
return { name: "frankenstein" };
},
}; // okay
const taskTwo: Task = {
id: "get-age",
run: () => {
return { age: 22 };
},
}; // okay
并拒绝无效的任务:
const taskThree: Task = {
id: "get-favourite-fruits",
run: () => { // error!
// Type '() => ("apple" | "banana")[]' is not assignable to type
// '(() => { name: string; }) | (() => { age: number; }) |
// (() => ("apple" | "strawberry" | "melon")[])
return ["apple", "banana"];
},
};
const taskFour: Task = { // error!
// ~~~~~~~~
// Type '{ id: "get-favourite-fruits"; run: () => { age: number; }; }'
// is not assignable to type 'Task'.
id: "get-favourite-fruits",
run: () => {
return { age: 123 };
},
};
无效任务的错误可能与您预期的特定错误略有不同。对于tasktree
,编译器抱怨run()
的返回与所有可能的任务
成员不兼容;“它不仅不是正确的数组,而且它甚至不是get name
或get age
的正确类型之一!”对于taskFour
,编译器看到run()
返回一个{age:number}
但是id
是get favority fruits
,并且在没有突出显示任何特定属性的情况下抱怨整个值是错误的
您希望Task
成为id
和run
三种不同可能的配对中的一种。您可以通过编程方式从Outputs
的每个Outputs
属性生成与此配对对应的值,然后通过所有映射属性获得所需的并集:
type Task = {
[K in keyof Outputs]: { id: K, run: () => Outputs[K] }
}[keyof Outputs];
/* produces
type Task = {
id: "get-name";
run: () => {
name: string;
};
} | {
id: "get-age";
run: () => {
age: number;
};
} | {
id: "get-favourite-fruits";
run: () => ("apple" | "strawberry" | "melon")[];
}*/
然后,代码的其余部分按需要工作。接受有效的任务:
const taskOne: Task = {
id: "get-name",
run: () => {
return { name: "frankenstein" };
},
}; // okay
const taskTwo: Task = {
id: "get-age",
run: () => {
return { age: 22 };
},
}; // okay
并拒绝无效的任务:
const taskThree: Task = {
id: "get-favourite-fruits",
run: () => { // error!
// Type '() => ("apple" | "banana")[]' is not assignable to type
// '(() => { name: string; }) | (() => { age: number; }) |
// (() => ("apple" | "strawberry" | "melon")[])
return ["apple", "banana"];
},
};
const taskFour: Task = { // error!
// ~~~~~~~~
// Type '{ id: "get-favourite-fruits"; run: () => { age: number; }; }'
// is not assignable to type 'Task'.
id: "get-favourite-fruits",
run: () => {
return { age: 123 };
},
};
无效任务的错误可能与您预期的特定错误略有不同。对于tasktree
,编译器抱怨run()
的返回与所有可能的任务
成员不兼容;“它不仅不是正确的数组,而且它甚至不是get name
或get age
的正确类型之一!”对于taskFour
,编译器看到run()
返回一个{age:number}
但是id
是get favority fruits
,并且在没有突出显示任何特定属性的情况下抱怨整个值是错误的
在您的任务类型中,这应该完成任务run:()=>{age:number}{name:string}代码>在您的任务类型中,这应该完成任务运行:()=>{age:number}{name:string}代码>我确实希望任务
就是这样!熟练地回答。它帮助我解决了问题,提高了我对打字脚本的理解。谢谢@jcalzI,你真希望Task
就是这样!熟练地回答。它帮助我解决了问题,提高了我对打字脚本的理解。谢谢@jcalz