Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

TypeScript thinks Msg type parameter of Dispatchable is covariant, but it should be contravariant #147

Open
@le0-0

Description

@le0-0

Let's say that Cat extends Animal – all Cats are Animals, just with even more restrictions on top. A Dispatchable<Animal> should be assignable to Dispatchable<Cat>. Only Cats will be dispatched to Dispatchable<Cat>, and all Cats are Animals, so a Dispatchable<Animal> is suited to process all Cats that is dispatched to it. Cat is a variant of Animal, but Dispatchable<Animal> is a variant of Dispatchable<Cat>, not the other way around. This means that the relationship between Dispatchable and its type parameter Msg is contravariant.

typeLeastRestrictedType={field1:"field1";};typeMiddleRestrictedType=LeastRestrictedType&{field2:"field2"};typeMostRestrictedType=MiddleRestrictedType&{field3:"field3"};constsystem=start();constactor=spawn(system,(state:undefined,message:MiddleRestrictedType):undefined=>{console.log(message.field1,message.field2);returnstate;});// This should fail because the actor actually uses restrictions// for MiddleRestrictedType that are not present on LeastRestrictedType.constsmallerActorRef:Dispatchable<LeastRestrictedType>=actor;dispatch(smallerActorRef,{field1:"field1",});// This fails, but shouldn't because all restrictions on MiddleRestrictedType// are also present on MostRestrictedType.constbiggerActorRef:Dispatchable<MostRestrictedType>=actor;dispatch(biggerActorRef,{field1:"field1",field2:"field2",field3:"field3",});

Expected Behavior

  • The TypeScript type system should realize that Dispatchable and its type parameter Msg are contravariant.
  • Trying to assign Dispatchable<Cat> to Dispatchable<Animal> should fail.
  • Trying to assign Dispatchable<Animal> to Dispatchable<Cat> should succeed.

Current Behavior

  • Trying to assign Dispatchable<Cat> to Dispatchable<Animal> succeeds, which leads to the bug illustrated above where the type system allows a message to be passed to a Dispatchable that doesn't have all the restrictions it assumes/needs.
  • Trying to assign Dispatchable<Animal> to Dispatchable<Cat> fails, even though all Dispatchable<Animal> are perfectly able to process all Cats.

Possible Solution

Probably some in/out annotations on type parameters in Dispatchable and associated types, to caress the type system into realizing the relationship between Dispatchable and its type parameter Msg is contravariant.

Context

I have met this roadblock many times. Most recently, I tried to create a testing function that expected a LocalActorRef<A | B>, to which I tried to pass a LocalActorRef<A | B | C>. If it can process A, B, and C, it will have no trouble if it only gets A and B, but the type system doesn't like this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp