Allow array items in TypeScript to be nullable (#19157)

* Allow array items in TypeScript to be nullable

* Regenerate samples

* Remove duplicate nullable array items codegen
This commit is contained in:
CirnoV (Sickle) 2024-07-16 16:40:17 +09:00 committed by GitHub
parent 75e3be39cb
commit a81b736b24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 40 additions and 59 deletions

View File

@ -629,7 +629,11 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
public String getTypeDeclaration(Schema p) { public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) { if (ModelUtils.isArraySchema(p)) {
Schema<?> items = ModelUtils.getSchemaItems(p); Schema<?> items = ModelUtils.getSchemaItems(p);
return getSchemaType(p) + "<" + getTypeDeclaration(unaliasSchema(items)) + ">"; String postfix = "";
if (Boolean.TRUE.equals(items.getNullable())) {
postfix = " | null";
}
return getSchemaType(p) + "<" + getTypeDeclaration(unaliasSchema(items)) + postfix + ">";
} else if (ModelUtils.isMapSchema(p)) { } else if (ModelUtils.isMapSchema(p)) {
Schema<?> inner = getSchemaAdditionalProperties(p); Schema<?> inner = getSchemaAdditionalProperties(p);
String nullSafeSuffix = getNullSafeAdditionalProps() ? " | undefined" : ""; String nullSafeSuffix = getNullSafeAdditionalProps() ? " | undefined" : "";

View File

@ -458,12 +458,8 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp
@Override @Override
public String getTypeDeclaration(Schema p) { public String getTypeDeclaration(Schema p) {
Schema inner; if (ModelUtils.isMapSchema(p)) {
if (ModelUtils.isArraySchema(p)) { Schema<?> inner = getSchemaAdditionalProperties(p);
inner = ModelUtils.getSchemaItems(p);
return this.getSchemaType(p) + "<" + this.getTypeDeclaration(unaliasSchema(inner)) + ">";
} else if (ModelUtils.isMapSchema(p)) {
inner = getSchemaAdditionalProperties(p);
String postfix = ""; String postfix = "";
if (Boolean.TRUE.equals(inner.getNullable())) { if (Boolean.TRUE.equals(inner.getNullable())) {
postfix = " | null"; postfix = " | null";

View File

@ -804,10 +804,6 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
newItemsDataType = "string"; newItemsDataType = "string";
var.dataTypeAlternate = var.dataTypeAlternate.replace("number", newItemsDataType); var.dataTypeAlternate = var.dataTypeAlternate.replace("number", newItemsDataType);
} }
if (var.itemsAreNullable()) {
var.dataTypeAlternate = var.dataTypeAlternate.replace(newItemsDataType, newItemsDataType + " | null");
}
} else if (var.isEnum) { } else if (var.isEnum) {
var.dataTypeAlternate = var.datatypeWithEnum; var.dataTypeAlternate = var.datatypeWithEnum;
} else if (var.isModel) { } else if (var.isModel) {
@ -825,10 +821,6 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
return parentIsEntity; return parentIsEntity;
} }
private boolean itemsAreNullable(ExtendedCodegenProperty var) {
return var.items.isNullable || (var.items.items != null && var.items.items.isNullable);
}
private void escapeOperationIds(OperationsMap operations) { private void escapeOperationIds(OperationsMap operations) {
for (CodegenOperation _op : operations.getOperations().getOperation()) { for (CodegenOperation _op : operations.getOperations().getOperation()) {
ExtendedCodegenOperation op = (ExtendedCodegenOperation) _op; ExtendedCodegenOperation op = (ExtendedCodegenOperation) _op;
@ -925,10 +917,6 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
newItemsDataType = "string"; newItemsDataType = "string";
param.dataTypeAlternate = param.dataTypeAlternate.replace("number", newItemsDataType); param.dataTypeAlternate = param.dataTypeAlternate.replace("number", newItemsDataType);
} }
if (param.itemsAreNullable()) {
param.dataTypeAlternate = param.dataTypeAlternate.replace(newItemsDataType, newItemsDataType + " | null");
}
} else if (param.isEnum) { } else if (param.isEnum) {
param.dataTypeAlternate = param.datatypeWithEnum; param.dataTypeAlternate = param.datatypeWithEnum;
} else if (param.isModel) { } else if (param.isModel) {
@ -1022,16 +1010,6 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
return false; return false;
} }
private static boolean itemsAreNullable(CodegenProperty items) {
if (items == null) {
return true;
}
if (items.items != null) {
return itemsAreNullable(items.items);
}
return items.isNullable;
}
private static String getItemsDataType(CodegenProperty items) { private static String getItemsDataType(CodegenProperty items) {
if (items == null) { if (items == null) {
return null; return null;
@ -1052,10 +1030,6 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
return TypeScriptFetchClientCodegen.itemsAreUniqueId(this.items); return TypeScriptFetchClientCodegen.itemsAreUniqueId(this.items);
} }
public boolean itemsAreNullable() {
return TypeScriptFetchClientCodegen.itemsAreNullable(this.items);
}
public String getItemsDataType() { public String getItemsDataType() {
return TypeScriptFetchClientCodegen.getItemsDataType(this.items); return TypeScriptFetchClientCodegen.getItemsDataType(this.items);
} }
@ -1206,10 +1180,6 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
return TypeScriptFetchClientCodegen.itemsAreUniqueId(this.items); return TypeScriptFetchClientCodegen.itemsAreUniqueId(this.items);
} }
public boolean itemsAreNullable() {
return TypeScriptFetchClientCodegen.itemsAreNullable(this.items);
}
public String getItemsDataType() { public String getItemsDataType() {
return TypeScriptFetchClientCodegen.getItemsDataType(this.items); return TypeScriptFetchClientCodegen.getItemsDataType(this.items);
} }

View File

@ -157,4 +157,15 @@ public class TypeScriptClientCodegenTest {
Assert.fail("Exception was thrown."); Assert.fail("Exception was thrown.");
} }
} }
@Test
public void arrayItemsCanBeNullable() throws Exception {
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/array-nullable-items.yaml");
final DefaultCodegen codegen = new TypeScriptClientCodegen();
codegen.setOpenAPI(openAPI);
final ArraySchema schema = (ArraySchema) openAPI.getComponents().getSchemas().get("ArrayWithNullableItemsModel")
.getProperties()
.get("foo");
Assert.assertEquals(codegen.getTypeDeclaration(schema), "Array<string | null>");
}
} }

View File

@ -1129,16 +1129,16 @@ export interface NullableClass {
'array_nullable_prop'?: Array<object> | null; 'array_nullable_prop'?: Array<object> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
'array_and_items_nullable_prop'?: Array<object> | null; 'array_and_items_nullable_prop'?: Array<object | null> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
'array_items_nullable'?: Array<object>; 'array_items_nullable'?: Array<object | null>;
/** /**
* *
* @type {{ [key: string]: object; }} * @type {{ [key: string]: object; }}

View File

@ -857,16 +857,16 @@ export interface NullableClass {
'array_nullable_prop'?: Array<object> | null; 'array_nullable_prop'?: Array<object> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
'array_and_items_nullable_prop'?: Array<object> | null; 'array_and_items_nullable_prop'?: Array<object | null> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
'array_items_nullable'?: Array<object>; 'array_items_nullable'?: Array<object | null>;
/** /**
* *
* @type {{ [key: string]: object; }} * @type {{ [key: string]: object; }}

View File

@ -64,16 +64,16 @@ export interface NullableClass {
arrayNullableProp?: Array<object> | null; arrayNullableProp?: Array<object> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
arrayAndItemsNullableProp?: Array<object> | null; arrayAndItemsNullableProp?: Array<object | null> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
arrayItemsNullable?: Array<object>; arrayItemsNullable?: Array<object | null>;
/** /**
* *
* @type {{ [key: string]: object; }} * @type {{ [key: string]: object; }}

View File

@ -76,7 +76,7 @@ export interface UpdatePetRequest {
export interface UpdatePetRegionsRequest { export interface UpdatePetRegionsRequest {
petId: number; petId: number;
newRegions: Array<Array<number>>; newRegions: Array<Array<number | null>>;
} }
export interface UpdatePetWithFormRequest { export interface UpdatePetWithFormRequest {
@ -509,7 +509,7 @@ export class PetApi extends runtime.BaseAPI {
/** /**
* Updates the pet regions. * Updates the pet regions.
*/ */
async updatePetRegions(petId: number, newRegions: Array<Array<number>>, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PetRegionsResponse> { async updatePetRegions(petId: number, newRegions: Array<Array<number | null>>, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PetRegionsResponse> {
const response = await this.updatePetRegionsRaw({ petId: petId, newRegions: newRegions }, initOverrides); const response = await this.updatePetRegionsRaw({ petId: petId, newRegions: newRegions }, initOverrides);
return await response.value(); return await response.value();
} }

View File

@ -166,10 +166,10 @@ export interface Pet {
status: PetStatusEnum; status: PetStatusEnum;
/** /**
* An array of all 15-minute time slots in 24 hours. * An array of all 15-minute time slots in 24 hours.
* @type {Array<Array<number>>} * @type {Array<Array<number | null>>}
* @memberof Pet * @memberof Pet
*/ */
regions?: Array<Array<number>>; regions?: Array<Array<number | null>>;
} }

View File

@ -34,10 +34,10 @@ export interface PetRegionsResponse {
meta: ResponseMeta; meta: ResponseMeta;
/** /**
* An array of all 15-minute time slots in 24 hours. * An array of all 15-minute time slots in 24 hours.
* @type {Array<Array<number>>} * @type {Array<Array<number | null>>}
* @memberof PetRegionsResponse * @memberof PetRegionsResponse
*/ */
data?: Array<Array<number>>; data?: Array<Array<number | null>>;
} }
/** /**

View File

@ -64,16 +64,16 @@ export interface NullableClass {
arrayNullableProp?: Array<object> | null; arrayNullableProp?: Array<object> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
arrayAndItemsNullableProp?: Array<object> | null; arrayAndItemsNullableProp?: Array<object | null> | null;
/** /**
* *
* @type {Array<object>} * @type {Array<object | null>}
* @memberof NullableClass * @memberof NullableClass
*/ */
arrayItemsNullable?: Array<object>; arrayItemsNullable?: Array<object | null>;
/** /**
* *
* @type {{ [key: string]: object; }} * @type {{ [key: string]: object; }}