Skip to content
This repository was archived by the owner on Sep 27, 2023. It is now read-only.

Add '| undefined' to optional properties #494

Merged
merged 1 commit into from
Oct 29, 2021
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
43 changes: 32 additions & 11 deletions src/TypeScriptGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ import {

type Selection = {
key: string;
schemaName?: string;
value?: any;
nodeType?: TypeID;
conditional?: boolean;
concreteType?: string;
ref?: string;
nodeSelections?: SelectionMap | null;
kind?: string;
documentName?: string;
schemaName?: string | undefined;
value?: any | undefined;
nodeType?: TypeID | undefined;
conditional?: boolean | undefined;
concreteType?: string | undefined;
ref?: string | undefined;
nodeSelections?: SelectionMap | null | undefined;
kind?: string | undefined;
documentName?: string | undefined;
};

type SelectionMap = Map<string, Selection>;
Expand Down Expand Up @@ -309,10 +309,31 @@ function exactObjectTypeAnnotation(

const idRegex = /^[$a-zA-Z_][$a-z0-9A-Z_]*$/;

// union optional types with undefined for compat with exactOptionalPropertyTypes
function createInexactOptionalType(type: ts.TypeNode): ts.TypeNode {
if (ts.isUnionTypeNode(type)) {
return ts.factory.updateUnionTypeNode(
type,
ts.factory.createNodeArray([
...type.types,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
])
);
} else {
return ts.factory.createUnionTypeNode([
type,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
]);
}
}

function objectTypeProperty(
propertyName: string,
type: ts.TypeNode,
options: { readonly?: boolean; optional?: boolean } = {}
options: {
readonly?: boolean | undefined;
optional?: boolean | undefined;
} = {}
): ts.PropertySignature {
const { optional, readonly = true } = options;
const modifiers = readonly
Expand All @@ -325,7 +346,7 @@ function objectTypeProperty(
? ts.factory.createIdentifier(propertyName)
: ts.factory.createStringLiteral(propertyName),
optional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
type
optional ? createInexactOptionalType(type) : type
);
}

Expand Down
27 changes: 18 additions & 9 deletions src/TypeScriptTypeTransformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type ScalarTypeMapping = {
export type State = {
generatedFragments: Set<string>;
generatedInputObjectTypes: {
[name: string]: ts.TypeNode | "pending";
[name: string]: ts.TypeLiteralNode | "pending";
};
matchFields: Map<string, ts.TypeNode>;
runtimeImports: Set<string>;
Expand Down Expand Up @@ -37,9 +37,7 @@ export function transformScalarType(
} else {
return ts.factory.createUnionTypeNode([
transformNonNullableScalarType(schema, type, state, objectProps),
ts.factory.createLiteralTypeNode(
ts.factory.createToken(ts.SyntaxKind.NullKeyword)
),
ts.factory.createLiteralTypeNode(ts.factory.createNull()),
]);
}
}
Expand Down Expand Up @@ -115,20 +113,29 @@ function transformGraphQLEnumType(
export function transformInputType(
schema: Schema,
type: TypeID,
state: State
state: State,
options: {
inputObjectProperty?: boolean | undefined;
} = {}
): ts.TypeNode {
const { inputObjectProperty } = options;
if (schema.isNonNull(type)) {
return transformNonNullableInputType(
schema,
schema.getNullableType(type),
state
);
} else if (inputObjectProperty) {
return ts.factory.createUnionTypeNode([
transformNonNullableInputType(schema, type, state),
ts.factory.createLiteralTypeNode(ts.factory.createNull()),
// add undefined to support exactOptionalPropertyTypes
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
]);
} else {
return ts.factory.createUnionTypeNode([
transformNonNullableInputType(schema, type, state),
ts.factory.createLiteralTypeNode(
ts.factory.createToken(ts.SyntaxKind.NullKeyword)
),
ts.factory.createLiteralTypeNode(ts.factory.createNull()),
]);
}
}
Expand Down Expand Up @@ -169,7 +176,9 @@ function transformNonNullableInputType(
!schema.isNonNull(fieldType)
? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
: undefined,
transformInputType(schema, fieldType, state)
transformInputType(schema, fieldType, state, {
inputObjectProperty: true,
})
);

return property;
Expand Down
Loading