mockdeep / typewiz

Automatically discover and add missing types in your TypeScript code
https://medium.com/@urish/manual-typing-is-no-fun-introducing-typewiz-58e3e8813f4c
1.1k stars 46 forks source link

Support non-ES5 target in tsconfig #83

Closed zxti closed 5 years ago

zxti commented 5 years ago

Thanks for your work on this project.

This is a feature request for support for tsconfig targets beyond ES5. I experimentally found that typewiz crashes on targets above ES5 (on things like destructuring params and whatnot).

I'd love to apply this to a large and newly migrated TS codebase that is targeting ES2017 (and more codebases beyond this one). However, downgrading the codebase to ES5 would be a large undertaking (and a backward step at that).

urish commented 5 years ago

Thank you for your feedback!

Can you some concrete code examples that crash TypeWiz?

I experimented with a simple destructuring variables, params and default values, and it seems like they all work correctly. Here are the test cases that worked for me (you can paste them in integration.spec.ts and run yarn test in the project to actually run them in your environment):

    it('should handle variable destructuring', () => {
        const input = `
            const test = x => x;
            let { foo } = { foo: 'bar' };
            test(foo);
        `;

        expect(typeWiz(input)).toBe(`
            const test = (x: string) => x;
            let { foo } = { foo: 'bar' };
            test(foo);
        `);
    });

    it('should handle default function parameters', () => {
        const input = `
            function f(n, x = 'world') {};
            f(1, 'hello');
        `;

        expect(typeWiz(input)).toBe(`
            function f(n: number, x = 'world') {};
            f(1, 'hello');
        `);
    });

    it('should handle function parameter destructuring', () => {
        const input = `
            function f({a, b}, c) {};
            f({a: 1, b: 2}, 5);
        `;

        expect(typeWiz(input)).toBe(`
            function f({a, b}: { a: number, b: number }, c: number) {};
            f({a: 1, b: 2}, 5);
        `);
    });
zxti commented 5 years ago

Sorry, I should have mentioned it's destructured params with defaults.

Here you go:

$ cat aoeu.ts
function greet({ who = "" }) {
  return `Hello, ${who}`;
}

console.log(greet({ who: "Uri" }));

$ cat tsconfig.json
{
  "compilerOptions": {
    "target": "es2017"
  }
}

$ node -r typewiz-node/dist/register aoeu.ts
/private/tmp/aoeu/aoeu.ts:1
(function (exports, require, module, __filename, __dirname) { function greet({ who = "" }) { $_$twiz("{ who = \"\" }", { who = "" }, 27, "/private/tmp/aoeu/aoeu.ts", "{}"); return `Hello, ${who}`; }
                                                                                                                         ^^^^^^^^

SyntaxError: Invalid shorthand property initializer
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:616:28)
    at Module.m._compile (/private/tmp/aoeu/node_modules/typewiz-node/node_modules/ts-node/src/index.ts:400:23)
    at Module.m._compile (/private/tmp/aoeu/node_modules/typewiz-node/src/node-register.ts:33:19)
    at Module._extensions..js (module.js:663:10)
    at require.extensions.(anonymous function) (/private/tmp/aoeu/node_modules/typewiz-node/src/node-register.ts:35:13)
    at Object.require.extensions.(anonymous function) [as .ts] (/private/tmp/aoeu/node_modules/typewiz-node/node_modules/ts-node/src/index.ts:403:12)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
urish commented 5 years ago

Thanks, I managed to reproduce this and write a failing test case for it:

    it('issue #83: invalid code produced for parameter destructuring with default values', () => {
        const input = `
            function greet({ who = "" }) {
                return 'Hello, ' + who;
            }
            greet('world');
        `;

        expect(typeWiz(input)).toBe(`
            function greet({ who = "" }: { who: string }) {
                return 'Hello, ' + who;
            }
            greet('world');
        `);
    });