Skip to content

Commit 28b412e

Browse files
authored
feat(dts-generator): improve support for function types (#487)
- support 'construct' functions using a "new:" parameter - allow to specify a 'this' type for a function, using 'this:' parameter - support marking parameters as optional by appending a '=' to the parameter's type (JSDoc notation) The parsing of JSDoc types supported these features already, but the transformation to the dts-generator's AST and the code generation still had to support it.
1 parent 27ce957 commit 28b412e

File tree

4 files changed

+29
-11
lines changed

4 files changed

+29
-11
lines changed

packages/dts-generator/src/phases/dts-code-gen.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,10 +861,13 @@ function genType(ast: Type, usage: string = "unknown"): string {
861861
return intersectionTypes.join(" & ");
862862
case "FunctionType":
863863
text = "";
864+
if (ast.isConstructor) {
865+
text += "new ";
866+
}
864867
if (!_.isEmpty(ast.typeParameters)) {
865868
text += `<${_.map(ast.typeParameters, (param) => param.name).join(", ")}>`; // TODO defaults, constraints, expressions
866869
}
867-
text += `(${_.map(ast.parameters, (param) => `${param.name}: ${genType(param.type, "parameter")}`).join(", ")})`;
870+
text += `(${_.map(ast.parameters, (param) => `${param.name}${param.optional ? "?" : ""}: ${genType(param.type, "parameter")}`).join(", ")})`;
868871
text += ` => ${ast.type ? genType(ast.type, "returnValue") : "void"}`;
869872
return text;
870873
case "NativeTSTypeExpression":

packages/dts-generator/src/types/ast.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ export interface FunctionType {
238238
parameters: Parameter[];
239239
typeParameters?: TypeParameter[];
240240
type?: Type;
241+
isConstructor?: boolean;
241242
}
242243

243244
export interface LiteralType {

packages/dts-generator/src/utils/ts-ast-type-builder.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
TypeReference,
77
UnionType,
88
TypeLiteral,
9+
Parameter,
910
} from "../types/ast.js";
1011

1112
/**
@@ -109,18 +110,25 @@ export class TSASTTypeBuilder {
109110
thisType: Type,
110111
constructorType: Type,
111112
): FunctionType {
113+
const parameters: Parameter[] = paramTypes.map((param, idx) => ({
114+
kind: "Parameter",
115+
name: "p" + (idx + 1), // JSDoc function types don't allow parameter names -> generate names
116+
type: param,
117+
optional: (param as any).optional,
118+
}));
119+
if (thisType != null) {
120+
// for TS, a 'this' type is specified as the first parameter type of a function
121+
parameters.unshift({
122+
kind: "Parameter",
123+
name: "this",
124+
type: thisType,
125+
});
126+
}
112127
return {
113128
kind: "FunctionType",
114-
parameters: paramTypes.map((param, idx) => ({
115-
kind: "Parameter",
116-
name: "p" + (idx + 1), // JSDoc function types don't allow parameter names -> generate names
117-
type: param,
118-
})),
119-
type: returnType,
120-
/* TODO not supported yet:
121-
"this": thisType,
122-
constructor: constructorType
123-
*/
129+
parameters,
130+
type: constructorType ?? returnType,
131+
isConstructor: constructorType != null,
124132
};
125133
}
126134
structure(structure: {

packages/dts-generator/src/utils/type-parser.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ export function TypeParser(
134134
next(":");
135135
returnType = parseType();
136136
}
137+
if (constructorType != null && returnType != null) {
138+
throw new SyntaxError(
139+
`A function signature must either use the 'new' keyword or have a return type, ` +
140+
`but not both (pos: ${rLexer.lastIndex}, input='${input}')`,
141+
);
142+
}
137143
type = builder.function(
138144
paramTypes,
139145
returnType,

0 commit comments

Comments
 (0)