Sha*_*ean 7 typescript typescript-generics
我试图根据传入的参数的泛型来推断方法的返回类型。但是,该参数是来自泛型接口的实现,因此,我假设打字稿推断将根据参数的基数来确定类型。
示例代码:
interface ICommand<T> {}
class GetSomethingByIdCommand implements ICommand<string> {
constructor(public readonly id: string) {}
}
class CommandBus implements ICommandBus {
execute<T>(command: ICommand<T>): T {
return null as any // ignore this, this will be called through an interface eitherway
}
}
const bus = new CommandBus()
// badResult is {}
let badResult = bus.execute(new GetSomethingByIdCommand('1'))
// goodResult is string
let goodResult = bus.execute<string>(new GetSomethingByIdCommand('1'))
Run Code Online (Sandbox Code Playgroud)
我想做的是第一次execute
调用,并让Typescript推断正确的返回值,string
在这种情况下,此返回值是基于GetSomethingByIdCommand
实现的。
我试过使用条件类型,但不确定这是否是解决方案或如何应用它。
您的问题是ICommand<T>
结构上不依赖T
(如@CRice的注释中所述)。
这是不推荐使用。(?链接到TypeScript FAQ条目,其中详细说明了一个与此案例几乎完全相同的案例,因此与我们可能在此处得到的官方用语一样近)
TypeScript的类型系统(主要)是结构性的,而不是名义上的:两种类型是相同的,当且仅当它们具有相同的形状(例如,具有相同的属性),并且与它们是否具有相同的名称无关。如果ICommand<T>
不是结构性依赖T
,没有它的性能有什么关系T
,然后ICommand<string>
是同一类型的ICommand<number>
,这是同类型的ICommand<ICommand<boolean>>
,这是相同的类型ICommand<{}>
。是的,这些都是不同的名称,但是类型系统不是名义上的,因此没有多大用处。
在这种情况下,您不能依靠类型推断。当您调用时execute()
,编译器会尝试推断T
in 的类型ICommand<T>
,但是没有任何可推断的类型。因此,它最终默认为空类型{}
。
解决此问题的方法是ICommand<T>
在某种程度上使结构依赖于T
,并确保实现的任何类型ICommand<Something>
都能正确执行此操作。给定示例代码,执行此操作的一种方法是:
interface ICommand<T> {
id: T;
}
Run Code Online (Sandbox Code Playgroud)
因此,ICommand<T>
必须具有id
type 的属性T
。幸运的是,GetSomethingByIdCommand
实际上确实具有id
type 的属性string
,如所要求implements ICommand<string>
,因此可以正常编译。
而且,重要的是,您确实需要进行推断:
// goodResult is inferred as string even without manually specifying T
let goodResult = bus.execute(new GetSomethingByIdCommand('1'))
Run Code Online (Sandbox Code Playgroud)
好的,希望能有所帮助;祝好运!
归档时间: |
|
查看次数: |
281 次 |
最近记录: |