Skip to content

Commit

Permalink
fix: generate type with private type error (#584)
Browse files Browse the repository at this point in the history
* fix: generate type with private type error

* chore: changeset

* chore: add comment
  • Loading branch information
luhc228 authored Sep 11, 2023
1 parent 8097a2c commit 4aee24c
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-crabs-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ice/pkg': patch
---

fix: generate types with private type error
2 changes: 2 additions & 0 deletions examples/react-component/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ interface ButtonProps {
onClick?: React.MouseEventHandler;
}

export const app: Application = { add: () => Promise.resolve(1) };

const Button: React.FunctionComponent<React.PropsWithChildren<ButtonProps>> = (props: ButtonProps) => {
const {
type = 'default',
Expand Down
4 changes: 4 additions & 0 deletions examples/react-component/src/typings.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
/// <reference types="@ice/pkg/types" />

interface Application {
add: () => Promise<number>;
}
88 changes: 68 additions & 20 deletions packages/pkg/src/helpers/dts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { TaskConfig } from '../types.js';
import { prepareSingleFileReplaceTscAliasPaths } from 'tsc-alias';
import fse from 'fs-extra';
import * as path from 'path';
import merge from 'lodash.merge';

export type FileExt = 'js' | 'ts' | 'tsx' | 'jsx' | 'mjs' | 'mts';

Expand Down Expand Up @@ -39,7 +40,7 @@ const normalizeDtsInput = (file: File, rootDir: string, outputDir: string): DtsI
};

interface DtsCompileOptions {

// In watch mode, it only contains the updated file names. In build mode, it contains all file names.
files: File[];
alias: TaskConfig['alias'];
rootDir: string;
Expand All @@ -52,16 +53,7 @@ export async function dtsCompile({ files, alias, rootDir, outputDir }: DtsCompil
return;
}

const tsCompilerOptions: ts.CompilerOptions = {
allowJs: true,
declaration: true,
emitDeclarationOnly: true,
incremental: true,
skipLibCheck: true,
outDir: outputDir,
rootDir: path.join(rootDir, 'src'),
paths: formatAliasToTSPathsConfig(alias),
};
const tsConfig = await getTSConfig(rootDir, outputDir, alias);

const logger = createLogger('dts');

Expand All @@ -81,7 +73,7 @@ export async function dtsCompile({ files, alias, rootDir, outputDir }: DtsCompil
const dtsFiles = {};

// Create ts host and custom the writeFile and readFile.
const host = ts.createCompilerHost(tsCompilerOptions);
const host = ts.createCompilerHost(tsConfig.options);
host.writeFile = (fileName, contents) => {
dtsFiles[fileName] = contents;
};
Expand All @@ -96,12 +88,24 @@ export async function dtsCompile({ files, alias, rootDir, outputDir }: DtsCompil
return _readFile(fileName);
};

// In order to only include the update files instead of all the files in the watch mode.
function getProgramRootNames(originalFilenames: string[]) {
// Should include all the resolved .d.ts file to avoid dts generate error:
// TS4025: Exported variable '<name>' has or is using private name '<name>'.
const dtsFilenames = originalFilenames.filter((filename) => filename.endsWith('.d.ts'));
const needCompileFileNames = _files.map(({ filePath }) => filePath);
return [...needCompileFileNames, ...dtsFilenames];
}

// Create ts program.
const program = ts.createProgram(
_files.map(({ filePath }) => filePath),
tsCompilerOptions,
const programOptions: ts.CreateProgramOptions = {
rootNames: getProgramRootNames(tsConfig.fileNames),
options: tsConfig.options,
host,
);
projectReferences: tsConfig.projectReferences,
configFileParsingDiagnostics: ts.getConfigFileParsingDiagnostics(tsConfig),
};
const program = ts.createProgram(programOptions);

logger.debug(`Initializing program takes ${timeFrom(dtsCompileStart)}`);

Expand All @@ -123,10 +127,8 @@ export async function dtsCompile({ files, alias, rootDir, outputDir }: DtsCompil
// Reason: https://github.com/microsoft/TypeScript/issues/30952#issuecomment-1114225407
const tsConfigLocalPath = path.join(rootDir, 'node_modules/pkg/tsconfig.json');
await fse.ensureFile(tsConfigLocalPath);
await fse.writeJSON(
tsConfigLocalPath,
{ compilerOptions: tsCompilerOptions },
);
await fse.writeJSON(tsConfigLocalPath, tsConfig, { spaces: 2 });

const runFile = await prepareSingleFileReplaceTscAliasPaths({
configFile: tsConfigLocalPath,
outDir: outputDir,
Expand All @@ -141,3 +143,49 @@ export async function dtsCompile({ files, alias, rootDir, outputDir }: DtsCompil

return result;
}

async function getTSConfig(
rootDir: string,
outputDir: string,
alias: TaskConfig['alias'],
) {
const defaultTSCompilerOptions: ts.CompilerOptions = {
allowJs: true,
declaration: true,
emitDeclarationOnly: true,
incremental: true,
skipLibCheck: true,
paths: formatAliasToTSPathsConfig(alias), // default add alias to paths
};
const projectTSConfig = await getProjectTSConfig(rootDir);
const tsConfig: ts.ParsedCommandLine = merge(
{ options: defaultTSCompilerOptions },
projectTSConfig,
{
options: {
outDir: outputDir,
rootDir: path.join(rootDir, 'src'),
},
},
);

return tsConfig;
}

async function getProjectTSConfig(rootDir: string): Promise<ts.ParsedCommandLine> {
const tsconfigPath = ts.findConfigFile(rootDir, ts.sys.fileExists);
if (tsconfigPath) {
const tsconfigFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
return ts.parseJsonConfigFileContent(
tsconfigFile.config,
ts.sys,
path.dirname(tsconfigPath),
);
}

return {
options: {},
fileNames: [],
errors: [],
};
}

0 comments on commit 4aee24c

Please sign in to comment.