microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.64k stars 12.44k forks source link

nested generics causing trouble in generated .d.ts #8105

Closed Sammons closed 8 years ago

Sammons commented 8 years ago

TypeScript Version: Version 1.8.2 Config

{
    "compilerOptions": {
        "target": "es6",
        "module": "commonjs",
        "moduleResolution": "node",
        "rootDir": "../src",
        "outDir": "../",
        "removeComments": true,
        "noLib": false,
        "noImplicitAny": false,
        "suppressImplicitAnyIndexErrors": true,
        "preserveConstEnums": true,
        "declaration": true,
        "sourceMap": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "noEmitOnError": false
    },
    "filesGlob": [
        "**/*.ts",
        "**/*.tsx",
        "!node_modules/**"
    ]
}

Source

export async function runSampleWorks<A, B, C, D, E>(
  a: bluebird<A>, b?: bluebird<B>, c?: bluebird<C>, d?: bluebird<D>, e?: bluebird<E>) {
  let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el));
  let func = <T>(f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T =>
    f.apply(this, result);
  let rfunc: typeof func & {} = func as any; // <- This is the only difference
  return rfunc
}

export async function runSampleBreaks<A, B, C, D, E>(
  a: bluebird<A>, b?: bluebird<B>, c?: bluebird<C>, d?: bluebird<D>, e?: bluebird<E>) {
  let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el));
  let func = <T>(f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T =>
    f.apply(this, result);
  let rfunc: typeof func = func as any; // <- This is the only difference
  return rfunc
}

Generated Types

export declare function runSampleWorks<A, B, C, D, E>(
    a: bluebird<A>, b?: bluebird<B>, c?: bluebird<C>, d?: bluebird<D>, e?: bluebird<E>)
    : Promise<(<T>(f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T) & {}>;

export declare function runSampleBreaks<A, B, C, D, E>(
    a: bluebird<A>, b?: bluebird<B>, c?: bluebird<C>, d?: bluebird<D>, e?: bluebird<E>)
    : Promise<<T > (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T >;

Expected behavior: Code that compiles generates types that compile, even with generics ;)

Actual behavior: The only way to get a type to generate a valid type declaration was to finagle it by adding & {} to an explicit typing. Sample of what didn't work and what does work are above. I'm not sure what triggered this behavior.

sheetalkamat commented 8 years ago

I think below is the expected behavior:

export declare function runSampleBreaks<A, B, C, D, E>(a: bluebird<A>, b?: bluebird<B>, c?: bluebird<C>, d?: bluebird<D>, e?: bluebird<E>): Promise<(<T>(f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T)>;