microsoft / microsoft/TypeScript
Covariance breaks when checking for `undefinded` in a type
@weswigham がすでに取り組んでいます。
2023年7月27日 から。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.4k
- 平均マージ
- 1日 19時間
- マージ済み PR(30日)
- 117
説明
Bug Report
I'm using the solid-js npm package which defines a type called Setter:
type Setter<T> = (undefined extends T ? () => undefined : {}) & (<U extends T>(value: (prev: T) => U) => U) & (<U extends T>(value: Exclude<U, Function>) => U) & (<U extends T>(value: Exclude<U, Function> | ((prev: T) => U)) => U);
I don't fully understand the reasoning behind it, but it's giving me some problems:
type Setter<T> = (undefined extends T ? () => undefined : {}) & (<U extends T>(value: (prev: T) => U) => U) & (<U extends T>(value: Exclude<U, Function>) => U) & (<U extends T>(value: Exclude<U, Function> | ((prev: T) => U)) => U);
class A { a = 1 }
class B extends A { b = 2 }
type Test<T> = { 0: Setter<T> };
declare const a: Test<A>;
const b: Test<B> = a; // ERROR!
I created an object with the property 0 which contains a Setter and it appears to not be covariant.
Inspecting the error it looks like that the problem is originated from this part undefined extends T ? () => undefined : {}, infact if I remove it this works, moreover the problem would still occur if that was the only part of the type:
type Setter<T> = undefined extends T ? () => undefined : {};
class A { a = 1 }
class B extends A { b = 2 }
type Test<T> = { 0: Setter<T> };
declare const a: Test<A>;
const b: Test<B> = a; // ERROR!
I think it is an error because the types are the same:
type TA = Test<A>;
// ^? type TA = { 0: {}; }
type TB = Test<B>;
// ^? type TB = { 0: {}; }
Additionally if Test were to be defined as [ Setter<T> ] the error would not occur:
type Setter<T> = undefined extends T ? () => undefined : {};
class A { a = 1 }
class B extends A { b = 2 }
type Test<T> = [ Setter<T> ];
declare const a: Test<A>;
const b: Test<B> = a; // OK?!?!
🔎 Search Terms
- undefined extends T
- covariance
- covariant
🕗 Version & Regression Information
This changed between versions 3.3.3 and 3.5.1. (The only playground version in which it doesn't occur is 3.3.3)
⏯ Playground Link
💻 Code
type Setter<T> = (undefined extends T ? () => undefined : {}) & (<U extends T>(value: (prev: T) => U) => U) & (<U extends T>(value: Exclude<U, Function>) => U) & (<U extends T>(value: Exclude<U, Function> | ((prev: T) => U)) => U);
// type Setter<T> = (<U extends T>(value: (prev: T) => U) => U) & (<U extends T>(value: Exclude<U, Function>) => U) & (<U extends T>(value: Exclude<U, Function> | ((prev: T) => U)) => U);
// type Setter<T> = undefined extends T ? () => undefined : {};
class A { a = 1 }
class B extends A { b = 2 }
type Test<T> = { 0: Setter<T> };
// type Test<T> = [ Setter<T> ];
declare const a: Test<A>;
const b: Test<B> = a; // ERROR!
type TA = Test<A>;
// ^?
type TB = Test<B>;
// ^?
🙁 Actual behavior
Can't assign b with the value of a.
It is wrong at the very least because it is not consistent
🙂 Expected behavior
Can assign b with the value of a
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
評価
この issue はまだ評価されていません。