Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected error/bad inference for generic composed function inside pipe #25791

Closed
OliverJAsh opened this issue Jul 19, 2018 · 1 comment · Fixed by #30193
Closed

Unexpected error/bad inference for generic composed function inside pipe #25791

OliverJAsh opened this issue Jul 19, 2018 · 1 comment · Fixed by #30193
Assignees
Labels
Needs Investigation This issue needs a team member to investigate its status.

Comments

@OliverJAsh
Copy link
Contributor

OliverJAsh commented Jul 19, 2018

TypeScript Version: 2.9.2

Search Terms: index signature pipe generic lost dictionary

Code

declare function pipe<V0, T1, T2, T3>(
    fn0: (x: V0) => T1,
    fn1: (x: T1) => T2,
    fn2: (x: T2) => T3,
): (x: V0) => T3;

declare function getStringDict(): { [index: string]: string };

declare function stringDictIdentity<T>(stringDict: {
    [index: string]: T;
}): { [index: string]: T };

/*
Without strict enabled:
Expected type (x: {}) => { [index: string]: string; }
Actual type (x: {}) => { [index: string]: {}; }

With strict enabled, unexpected type error:
Argument of type '<T>(stringDict: { [index: string]: T; }) => { [index: string]: T; }' is not assignable to parameter of type '(x: {}) => { [index: string]: {}; }'.
  Types of parameters 'stringDict' and 'x' are incompatible.
    Type '{}' is not assignable to type '{ [index: string]: {}; }'.
      Index signature is missing in type '{}'.
 */
const fn = pipe(
    getStringDict,
    x => x,
    stringDictIdentity,
);

//
// Workarounds
//

declare function identity<T>(a: T): T;
const fn2 = pipe(
    getStringDict,
    identity,
    stringDictIdentity,
);

const fn3 = pipe(
    getStringDict,
    x => x,
    x => stringDictIdentity(x),
);
@OliverJAsh
Copy link
Contributor Author

Revisiting this. I believe the issue can be narrowed down to:

{
    declare const pipe: {
        <A, B, C, D>(ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): (a: A) => D;
    };

    declare const getArray: () => string[];
    declare const first: <T>(ts: T[]) => T;

    /*
    Without `strictFunctionTypes` enabled:
    Expected type: `(a: {}) => string`
    Actual type: `(a: {}) => {}`
    */
    const fn = pipe(
        getArray,
        x => x,
        /*
        With `strictFunctionTypes` enabled, unexpected type error:
        Argument of type '<T>(ts: T[]) => T' is not assignable to parameter of type '(c: {}) => {}'.
            Types of parameters 'ts' and 'c' are incompatible.
                Type '{}' is missing the following properties from type '{}[]': length, pop, push, concat, and 25 more.
        */
        first,
    );

    // Workaround 1: use `identity` function
    declare const identity: <T>(value: T) => T;
    const fn2 = pipe(
        getArray,
        identity,
        first,
    );

    // Workaround 2: wrap last function
    const fn3 = pipe(
        getArray,
        x => x,
        x => first(x),
    );
}

Any ideas @mhegazy @weswigham? Does this help?

@OliverJAsh OliverJAsh changed the title Unexpected error/bad inference for generic inside of index signature Unexpected error/bad inference for generic composed function inside pipe Feb 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants