Extends is not working as expected (could be because it's an interface instead of a type)
vinassefranche opened this issue · 0 comments
vinassefranche commented
I'm using typescript@4.3.5.
Extending two different types from the same NewType
makes them so their types are considered the same.
See the following example where a variable of type Extends2
can be used as the parameter of a method which declares a type Extends1
:
import { Extends, Newtype } from 'newtype-ts';
interface Base extends Newtype<{readonly Base: unique symbol}, number> {}
interface Extends1 extends Extends<Base, {readonly Extends1: unique symbol}>{}
interface Extends2 extends Extends<Base, {readonly Extends2: unique symbol}>{}
declare const methodOnExtends1: (a: Extends1) => void;
declare const extends2: Extends2;
methodOnExtends1(extends2) // does not fail while it should
// things that as working as expected:
declare const methodOnBase: (a: Base) => void;
declare const base: Base;
methodOnExtends1(base); // fails, as expected
methodOnBase(extends2) // does not fail, as expected
What is really strange is that if I 'recompose' the type myself, it works as expected:
declare const methodOnExtends1Recomposed: (a: {_URI: Extends1['_URI'], _A: Extends1['_A']}) => void;
declare const extends2Recomposed: {_URI: Extends2['_URI'], _A: Extends2['_A']};
methodOnExtends1Recomposed(extends2Recomposed); // fails as expected
I found out that declaring Extends
as a type
instead of an interface
fixes the issue:
import { AnyNewtype, Newtype, URIOf, CarrierOf } from 'newtype-ts';
export type Extends<N extends AnyNewtype, Tags extends object> = Newtype<Tags & URIOf<N>, CarrierOf<N>>
interface Base
extends Newtype<{readonly Base: unique symbol}, number> {}
interface Extends1
extends Extends<Base, {readonly Extends1: unique symbol}>{}
interface Extends2
extends Extends<Base, {readonly Extends2: unique symbol}>{}
declare const methodOnExtends1: (a: Extends1) => void;
declare const extends2: Extends2;
methodOnExtends1(extends2) // fails, as expected
// non-regression verifications:
declare const methodOnBase: (a: Base) => void;
declare const base: Base;
methodOnExtends1(base); // fails, as expected
methodOnBase(extends2) // does not fail, as expected
Any explanation on this? Should we update the declaration of Extends
to be with type
(I can do the P.R. if needed)?
Thanks in advance!