Skip to content

Generic function with rest parameter assignability not transitive #32948

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.

Wesley Wigham (@weswigham)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

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