Skip to content

Generic function with rest parameter assignability not transitive #32948

Closed
@AnyhowStep

Description

@AnyhowStep

TypeScript Version:

Search Terms:

Code

/**
 * --strictFunctionTypes
 */

export type ExtendedMapper<HandledInputT, OutputT, ArgsT extends any[]> = (
    (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT
);

//type a = (name: string, mixed: any, args_0: any) => any
type a = ExtendedMapper<any, any, [any]>;
//type b = (name: string, mixed: any, ...args: any[]) => any
type b = ExtendedMapper<any, any, any[]>;
//3.5.1, typescript@3.7.0-dev.20190815
//Expected: "y"
//Actual  : "y"
//https://github.com/microsoft/TypeScript/pull/32924#issuecomment-521819476
//https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/40404/artifacts?artifactName=tgz&fileId=AD9D22CF70561BEAF5758E061B61D3FF891ADF664E37C532F5881393CE7DC83202&fileName=/typescript-3.7.0-insiders.20190815.tgz
//Expected: "y"
//Actual  : "n" <-- Intentional?
type test = a extends b ? "y" : "n"

type a2 = (name: string, mixed: any, args_0: any) => any
type b2 = (name: string, mixed: any, ...args: any[]) => any
//3.5.1, typescript@3.7.0-dev.20190815
//Expected: "y"
//Actual  : "y"
//https://github.com/microsoft/TypeScript/pull/32924#issuecomment-521819476
//https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/40404/artifacts?artifactName=tgz&fileId=AD9D22CF70561BEAF5758E061B61D3FF891ADF664E37C532F5881393CE7DC83202&fileName=/typescript-3.7.0-insiders.20190815.tgz
//Expected: "y"
//Actual  : "y"
type test2 = a2 extends b2 ? "y" : "n"

//a extends b2 extends b
//However, a DOES NOT extend b
//It seems assignability is not transitive...

//"y" for all versions
type aExtendsB2 = a extends b2 ? "y" : "n"
//"y" for all versions
type b2ExtendsB = b2 extends b ? "y" : "n"

type TakeExtendedMapperRest<MapperT extends b> = (
    ["Blah", MapperT]
);

//Works in 3.5.1
//Fails for https://github.com/microsoft/TypeScript/pull/32924#issuecomment-521819476
export type ShouldWorkButFails<T extends a> = (
    //Type 'ExtendedMapper<any, any, [any]>' does not satisfy the constraint 'ExtendedMapper<any, any, any[]>'.
    //  Property '0' is missing in type 'any[]' but required in type '[any]'.ts(2344)
    //a -> b not allowed
    TakeExtendedMapperRest<T>
    //                     ~
);

//Works in 3.5.1
//Works in https://github.com/microsoft/TypeScript/pull/32924#issuecomment-521819476
export type Workaround<T extends a> = (
    TakeExtendedMapperRest<
        //OK!
        //Takes advantage of a -> b2 -> b being allowed
        Extract<T, b2>
    >
);

//Works in 3.5.1
//Fails in https://github.com/microsoft/TypeScript/pull/32924#issuecomment-521819476
type WorkaroundTest = TakeExtendedMapperRest<a>;

//Works in 3.5.1
//Works in https://github.com/microsoft/TypeScript/pull/32924#issuecomment-521819476
//type WorkaroundTest2 = ["Blah", ExtendedMapper<any, any, [any]>]
type WorkaroundTest2 = Workaround<a>; //Success

Expected behavior:

Build in #32924 (comment) should behave the same as 3.5.1 and typescript@3.7.0-dev.20190815

Assignability should be transitive.

a -> b2 -> b should imply a -> b

Actual behavior:

Assignability is not transitive

a -> b2 -> b but not a -> b

Playground Link:
Playground

Related Issues:

#32924 (comment)

#32924 (comment)

#32924 (comment)

I'm not sure which commit introduced this problem.

@weswigham

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions