具有通用方法和继承的打字稿工厂,错误不可分配给类型
Posted
技术标签:
【中文标题】具有通用方法和继承的打字稿工厂,错误不可分配给类型【英文标题】:Typescript factory with generic method and inheritance, error is not assignable to type 【发布时间】:2020-12-14 09:45:56 【问题描述】:为什么打字稿编译器不接受以下代码? (我试图让代码不言自明)。
我收到以下错误 Type 'Dog' is not assignable to type 'K'
和 Type 'Drone' is not assignable to type 'K'
。
我知道我可以通过使用联合类型 Dog | Drone
作为我工厂的输出类型来使用解决方法,但这意味着更新每个创建的新对象的签名。我想知道是否有一种“通用”的方式来声明这一点。
interface executeFn<I>
(param: I): string
interface Robot<I>
execute: executeFn<I>
interface BaseOrder
name: string
interface DogOrder extends BaseOrder
action: string
interface DroneOrder extends BaseOrder
destination: string
class Dog implements Robot<DogOrder>
execute(order: DogOrder): string
return 'The action is ' + order.action
class Drone implements Robot<DroneOrder>
execute(order: DroneOrder): string
return 'The destination is ' + order.destination
function robotFactory<T extends BaseOrder, K extends Robot<BaseOrder>>(
param: T
): K
if (((param as unknown) as DogOrder).action)
return new Dog()
return new Drone()
请注意,我也尝试更改泛型方法签名,但这并不能解决 pb。
interface executeFn<I>
<T extends I>(param: T): string
【问题讨论】:
【参考方案1】:编译器会正确警告您 K 可能并不总是 Dog 或 Drone。
class DroneAdversary implements Robot<DroneOrder>
execute(order: DroneOrder): string
return 'The destination is ' + order.destination
const adversary = robotFactory<DroneOrder, DroneAdversary>(
name: 'aaa',
destination: 'dest'
); // adversary type is DroneAdversary
我会超载:
function isDogOrder(order: BaseOrder): order is DogOrder
return !!((order as DogOrder).action);
function robotFactoryOverload(order: DogOrder): Dog
function robotFactoryOverload(order: DroneOrder): Drone
function robotFactoryOverload(order: DogOrder | DroneOrder): Dog | Drone
if (isDogOrder(order))
return new Dog()
else
return new Drone()
const x = robotFactoryOverload(
name: 'aaa',
destination: 'sasas'
);
【讨论】:
Thx @Lesiak,使用联合类型Dog | Drone
作为返回类型,我已经提到了这个潜在的解决方案,但这意味着每次添加新类型的机器人时都要更新签名。我希望有一个解决方案,我不必这样做。
然后为联合 type Robot = Dog | Drone
添加一个类型。你只有一个地方可以更新。
感谢type predicate
,我不知道我们可以在打字稿中做到这一点***.com/questions/40081332/…【参考方案2】:
为了扩展 Lesiak 的答案,如果您定义 Robot
类型联合,则可以自动定义所有重载,如果您可能有很多重载,这会有所帮助。
type AnyRobot = Dog | Drone
type RobotForOrder<O extends BaseOrder, R = AnyRobot> = R extends Robot<O> ? R : never
function robotFactory<T extends BaseOrder> (order: T): RobotForOrder<T>
function robotFactory<T extends BaseOrder> (order: T): AnyRobot
if (isDogOrder(order))
return new Dog()
return new Drone()
【讨论】:
以上是关于具有通用方法和继承的打字稿工厂,错误不可分配给类型的主要内容,如果未能解决你的问题,请参考以下文章
打字稿,JSON.parse 错误:“类型 'null' 不可分配给类型 'string'。”
使用反应成帧器类型'()=> void'的打字稿错误不可分配给类型'未定义'
打字稿错误:类型 'string' 不可分配给类型 '"allName" | `allName.$number.nestedArray`' 在反应钩子形式