preactjs / wmr

👩‍🚀 The tiny all-in-one development tool for modern web apps.
https://wmr.dev/
MIT License
4.92k stars 109 forks source link

TypeScript 4.5 `type` modifiers on imported names are not supported. #902

Open danielweck opened 2 years ago

danielweck commented 2 years ago

Describe the bug

TypeScript 4.5 type modifiers on imported names are not supported.

https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#type-on-import-names

To Reproduce

For example, this works:

import type { Options, VNode } from 'preact';
import { options } from 'preact'; // eslint-disable-line no-duplicate-imports

...but this breaks:

import { type Options, type VNode, options } from 'preact';
SyntaxError: Error transforming /PATH/TO/code.ts: Unexpected token, expected ","

Expected behavior

Preact WMR should support all the tasty goodness of TypeScript syntactic sugar :)

Bug occurs with:

rschristian commented 2 years ago

Issue to track in sucrase: https://github.com/alangpierce/sucrase/issues/668#issue-1070610227

danielweck commented 2 years ago

FYI, I use this Preact WMR plugin to work around this problem:

config.plugins.push({
    name: 'TypeScript 4.5 type modifier on imported names removal plugin',
    enforce: 'pre',

    transform(code, id) {
        if (!/\.tsx?$/.test(id)) return;

        // TODO: is this really necessary in WMR's latest version?
        if (id[0] === '\0' || id[0] === '\b') return;

        if (config.mode === 'build' || config.mode === 'start') {
            const re = /^import(.*)({.+})\s*from\s*['|"](.+)['|"]/gm;
            return {
                code: code.replace(re, (match, $1, $2, $3) => {
                    if (!$2.includes('type ')) {
                        return match; // preserve as-is
                    }
                    return `import${$1}${$2.replace(/type /g, '')} from '${$3}'`;
                }),
                map: null,
            };
        }
    },
});