Skip to content

Try aliasing preact typescript declaration to fix ts errors #11088

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

Merged
merged 4 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/feedback/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"build:dev": "run-p build:transpile build:types",
"build:types": "run-s build:types:core build:types:downlevel",
"build:types:core": "tsc -p tsconfig.types.json",
"build:types:downlevel": "yarn downlevel-dts build/npm/types build/npm/types-ts3.8 --to ts3.8",
"build:types:downlevel": "yarn downlevel-dts build/npm/types build/npm/types-ts3.8 --to ts3.8 && yarn node ./scripts/shim-preact-export.js",
"build:watch": "run-p build:transpile:watch build:bundle:watch build:types:watch",
"build:dev:watch": "run-p build:transpile:watch build:types:watch",
"build:transpile:watch": "yarn build:transpile --watch",
Expand Down
75 changes: 75 additions & 0 deletions packages/feedback/scripts/shim-preact-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// preact does not support more modern TypeScript versions, which breaks our users that depend on older
// TypeScript versions. To fix this, we shim the types from preact to be any and remove the dependency on preact
// for types directly. This script is meant to be run after the build/npm/types-ts3.8 directory is created.

// Path: build/npm/types-ts3.8/global.d.ts

const fs = require('fs');
const path = require('path');

/**
* This regex looks for preact imports we can replace and shim out.
*
* Example:
* import { ComponentChildren, VNode } from 'preact';
*/
const preactImportRegex = /import\s*{\s*([\w\s,]+)\s*}\s*from\s*'preact'\s*;?/;

function walk(dir) {
const files = fs.readdirSync(dir);
files.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.lstatSync(filePath);
if (stat.isDirectory()) {
walk(filePath);
} else {
if (filePath.endsWith('.d.ts')) {
const content = fs.readFileSync(filePath, 'utf8');
const capture = preactImportRegex.exec(content);
if (capture) {
const groups = capture[1].split(',').map(s => s.trim());
Copy link
Member Author

@AbhiPrasad AbhiPrasad Mar 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shrewd readers would notice that this breaks completely with multiline imports

import {
  x,
  y,
  z,
} from 'preact';

I know, but we can cross that bridge when we come to it - prefer to get this out to unblock asap.


// This generates a shim snippet to replace the type imports from preact
// It generates a snippet based on the capture groups of preactImportRegex.
//
// Example:
//
// import type { ComponentChildren, VNode } from 'preact';
// becomes
// type ComponentChildren: any;
// type VNode: any;
const snippet = groups.reduce((acc, curr) => {
const searchableValue = curr.includes(' as ') ? curr.split(' as ')[1] : curr;

// look to see if imported as value, then we have to use declare const
if (content.includes(`typeof ${searchableValue}`)) {
return `${acc}declare const ${searchableValue}: any;\n`;
}

// look to see if generic type like Foo<T>
if (content.includes(`${searchableValue}<`)) {
return `${acc}type ${searchableValue}<T> = any;\n`;
}

// otherwise we can just leave as type
return `${acc}type ${searchableValue} = any;\n`;
}, '');

// we then can remove the import from preact
const newContent = content.replace(preactImportRegex, '// replaced import from preact');

// and write the new content to the file
fs.writeFileSync(filePath, snippet + newContent, 'utf8');
}
}
}
});
}

function run() {
// recurse through build/npm/types-ts3.8 directory
const dir = path.join('build', 'npm', 'types-ts3.8');
walk(dir);
}

run();