typescript - 打字稿:使用特定的扩展接口来满足通用的“扩展”类型参数?
问题描述
这是一个小代码示例(旁注:我正在运行 Typescript v3.8.3):
interface IOptions<T> {
arg: T;
}
interface IExtraOptions extends IOptions<number> {
arg2: string;
}
type Func = <T, OptionsT extends IOptions<T>>(options: OptionsT) => T;
const f: Func = (options: IExtraOptions): number => {
return options.arg2 === 'dev' ? 0 : options.arg;
};
我希望这可以工作,因为IExtraOptions
扩展IOptions
并因此满足OptionsT extends IOptions<T>
约束,但我得到:
类型“OptionsT”不可分配给类型“IExtraOptions”。
“IOptions”类型中缺少属性“arg2”,但在“IExtraOptions”类型中是必需的。ts(2322)
完全删除OptionsT
参数并仅用IOptions<T>
作“选项”的类型参数会产生相同的错误。用非默认类型替换“数字”也不能解决它。有人知道我在做什么错吗?
解决方案
如果你有一个泛型函数,函数的泛型类型参数是由调用者决定的,而不是让实现修复为一些任意类型。例如,给定您的示例,此调用将是有效f<boolean, IOptions<boolean>>({ arg: true })
的,并且您指定的实现不会返回满足这些类型参数的对象。
结论是,如果你有一个泛型函数,通常只有泛型函数才能满足实现(尽管使用非常松散的类型,例如any
, never
orunknown
也可能工作)。
如果你想创建专门的函数,不要使用泛型函数,使用恰好是函数的泛型类型:
type Func <T, OptionsT extends IOptions<T>> =(options: OptionsT) => T;
const f: Func<number, IExtraOptions> = (options ) => {
return options.arg2 === 'dev' ? 0 : options.arg;
};
您也可以从中派生T
出TOptions
一些简化的东西:
type Func <OptionsT extends IOptions<any>> =(options: OptionsT) => OptionsT['arg'];
const f: Func<IExtraOptions> = (options ) => {
return options.arg2 === 'dev' ? 0 : options.arg;
};
推荐阅读
- mongodb - 如何丢弃引发错误的记录?
- mysql - ASP.NET 数据表:无法启用约束。一行或多行包含违反使用 MySql 的非空、唯一或外键约束的值
- laravel - 按属性获取价值
- spring-boot - SpringBoot with multi-project Gradle --> 主类名未配置,无法解析
- javascript - angular6中编辑表单的预选选项(下拉)
- vb.net - VB.net 重置 SMTP 连接
- spss - IF 条件下的缺失值
- javascript - Number(number).toLocaleString() 为负数添加长连字符而不是减号
- sql-server - 必须声明标量变量“@@procid”
- angular - Angularfire2 我正在尝试获取 Angular Fire 文档的字段名称