Typescript: variance of subtyping

Created on 4 Sep 2019  Β·  5Comments  Β·  Source: microsoft/TypeScript


TypeScript Version: 3.6


Search Terms:

subtyping invariant covariant

| Read and write | variance |
| --- | --- |
| read and write | invariance |
| readonly | covariance |
| writeonly | contravariance |

Code

interface a {
  foo?: string
}

interface b extends a { 
  foo: string // subtype of string | undefined
}

declare const b: b;

const a: a = b;

a.foo = undefined; // now b has property `foo:undefined`
console.log(b.foo);

Expected behavior:

Can't extends when property foo of b isn't readonly

Actual behavior:

It has no warning and no error

Playground Link:

Related Issues:

Design Limitation

Most helpful comment

Doesn't TS add new breaking behavior behind a flag?

Anything that relies on unsound extends can turn it off, and everyone else that wants more safety, and are masochistic can use the new flag

All 5 comments

A not-so-great workaround at the moment is to just make all your properties readonly always, and treat everything as immutable.

I personally do that but it's unnerving that I can slip up and make a mistake, and not have the compiler tell me about it

I don't think we're likely to make extends sound with respect to variance. Many crusty old OO codebases violate it.

Intersection behaves better, so I'd recommend that over extends if you care about variance.

Doesn't TS add new breaking behavior behind a flag?

Anything that relies on unsound extends can turn it off, and everyone else that wants more safety, and are masochistic can use the new flag

I'm curious if anyone's run into issues in real code arising from this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DanielRosenwasser picture DanielRosenwasser  Β·  3Comments

manekinekko picture manekinekko  Β·  3Comments

fwanicka picture fwanicka  Β·  3Comments

dlaberge picture dlaberge  Β·  3Comments

CyrusNajmabadi picture CyrusNajmabadi  Β·  3Comments