// @strict: true type Either = Left | Right; class Left { readonly _tag: 'Left' = 'Left' readonly _A!: A readonly _L!: L constructor(readonly value: L) {} /** The given function is applied if this is a `Right` */ map(f: (a: A) => B): Either { return this as any } ap(fab: Either B>): Either { return null as any } } class Right { readonly _tag: 'Right' = 'Right' readonly _A!: A readonly _L!: L constructor(readonly value: A) {} map(f: (a: A) => B): Either { return new Right(f(this.value)) } ap(fab: Either B>): Either { return null as any; } } class Type { readonly _A!: A; readonly _O!: O; readonly _I!: I; constructor( /** a unique name for this codec */ readonly name: string, /** a custom type guard */ readonly is: (u: unknown) => u is A, /** succeeds if a value of type I can be decoded to a value of type A */ readonly validate: (input: I, context: {}[]) => Either<{}[], A>, /** converts a value of type A to a value of type O */ readonly encode: (a: A) => O ) {} /** a version of `validate` with a default context */ decode(i: I): Either<{}[], A> { return null as any; } } interface Any extends Type {} type TypeOf = C["_A"]; type ToB = { [k in keyof S]: TypeOf }; type ToA = { [k in keyof S]: Type }; type NeededInfo = { ASchema: ToA; }; export type MyInfo = NeededInfo>; const tmp1: MyInfo = null!; function tmp2(n: N) {} // tmp2(tmp1); // uncommenting this line removes a type error from a completely unrelated line ?? (see test 1, needs to behave the same) class Server {} export class MyServer extends Server {} // not assignable error at `MyInfo`