typescript - 为什么映射类型不能使用通用但有限的键完全解析查找?
问题描述
这是问题的简化:
type Animal = 'dog' | 'cat';
type AnimalSound<T extends Animal> = T extends 'dog'
? 'woof'
: T extends 'cat'
? 'meow'
: never;
const animalSoundMap: {[K in Animal]: AnimalSound<K>} = {
dog: 'woof',
cat: 'meow',
};
const lookupSound = <T extends Animal>(animal: T): AnimalSound<T> => {
const sound = animalSoundMap[animal];
return sound;
}
该return
行是错误的;错误消息表明该sound
变量已解析为'woof' | 'meow'
,即使TS似乎应该能够根据AnimalSound<T>
的类型键入它animalSoundMap
。那么为什么类型检查器不喜欢它呢?
解决方案
为了让 TypeScript 开心,我相信你应该坚持使用@TJ Crowder 的解决方案或者这个:
type Animal = 'dog' | 'cat';
type AnimalSound<T extends Animal> = T extends 'dog'
? 'woof'
: T extends 'cat'
? 'meow'
: never;
const animalSoundMap: { [K in Animal]: AnimalSound<K> } = {
dog: 'woof',
cat: 'meow',
};
const lookupSound = <
AnimalName extends Animal,
AnimalMap extends { [Name in AnimalName]: AnimalSound<Name> }
>(animalMap: AnimalMap, animal: AnimalName):
AnimalMap[AnimalName] =>
animalMap[animal]
如果要推断返回类型,还应该推断并制作函数参数的一部分animalMap
。
操场
您甚至不需要定义显式返回类型,TS 能够从函数体中推断出它:
const lookupSound = <T extends Animal>(animal: T)=> {
const sound = animalSoundMap[animal];
return sound;
}
const result = lookupSound('cat') // "meow"
条件类型不能以您期望的方式在返回类型的地方工作。如果您在函数重载中使用条件类型,它可能会起作用:
function lookupSound<T extends Animal>(animal: T): AnimalSound<T>
function lookupSound<T extends Animal>(animal: T) {
const sound = animalSoundMap[animal];
return sound;
}
推荐阅读
- c++ - 在 qml js 函数中实例化 c++ 结构
- sql - SQL Lead/Lag until a certain condition and update the previous/next rows with a value from the row that hit the condition
- android - DialogFragment 中的 Spinner 未触发 setOnSelectedItemListener
- django - get_%field%_display 没有实例
- php - 将 PHP 转换为 Codeigniter 框架
- php - 使用模板将数据从控制器传递到视图
- javascript - 单击行时选中复选框 angular 4
- c# - 如何在 Windows 10(10 月更新)中获取剪贴板历史记录?
- php - Laravel 5.2 在用户注册时上传图片到上传文件夹
- linux - 如果文件在linux的子目录中不存在,则检索父目录名称的命令