Skip to content

Commit e7228fa

Browse files
committed
fix(ast/estree): fix optional field of TSMappedType in TS-ESTree AST (#10874)
Part of #9705. Recent changes in TS-ESLint made `TSMappedType`'s `optional` field default to `false` instead of `null`. Update our TS-ESTree AST to match it.
1 parent 6f0638a commit e7228fa

File tree

7 files changed

+34
-329
lines changed

7 files changed

+34
-329
lines changed

crates/oxc_ast/src/ast/ts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,6 +1447,7 @@ pub struct TSMappedType<'a> {
14471447
/// type Qux = { [P in keyof T]: T[P] }
14481448
/// // ^ None
14491449
/// ```
1450+
#[estree(via = TSMappedTypeOptional)]
14501451
pub optional: Option<TSMappedTypeModifierOperator>,
14511452
/// Readonly modifier before keyed index signature
14521453
///

crates/oxc_ast/src/generated/derive_estree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3166,7 +3166,7 @@ impl ESTree for TSMappedType<'_> {
31663166
state.serialize_field("end", &self.span.end);
31673167
state.serialize_field("nameType", &self.name_type);
31683168
state.serialize_field("typeAnnotation", &self.type_annotation);
3169-
state.serialize_field("optional", &self.optional);
3169+
state.serialize_field("optional", &crate::serialize::TSMappedTypeOptional(self));
31703170
state.serialize_field("readonly", &self.readonly);
31713171
state.serialize_field("key", &crate::serialize::TSMappedTypeKey(self));
31723172
state.serialize_field("constraint", &crate::serialize::TSMappedTypeConstraint(self));

crates/oxc_ast/src/serialize.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,30 @@ impl ESTree for TSModuleDeclarationGlobal<'_, '_> {
12861286
}
12871287
}
12881288

1289+
/// Serializer for `optional` field of `TSMappedType`.
1290+
///
1291+
/// `None` is serialized as `false`.
1292+
#[ast_meta]
1293+
#[estree(
1294+
ts_type = "TSMappedTypeModifierOperator | false",
1295+
raw_deser = "
1296+
let optional = DESER[Option<TSMappedTypeModifierOperator>](POS_OFFSET.optional) || false;
1297+
if (optional === null) optional = false;
1298+
optional
1299+
"
1300+
)]
1301+
pub struct TSMappedTypeOptional<'a, 'b>(pub &'b TSMappedType<'a>);
1302+
1303+
impl ESTree for TSMappedTypeOptional<'_, '_> {
1304+
fn serialize<S: Serializer>(&self, serializer: S) {
1305+
if let Some(optional) = self.0.optional {
1306+
optional.serialize(serializer);
1307+
} else {
1308+
False(()).serialize(serializer);
1309+
}
1310+
}
1311+
}
1312+
12891313
/// Serializer for `key` and `constraint` field of `TSMappedType`.
12901314
#[ast_meta]
12911315
#[estree(

napi/parser/generated/deserialize/js.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1897,14 +1897,16 @@ function deserializeTSConstructorType(pos) {
18971897
}
18981898

18991899
function deserializeTSMappedType(pos) {
1900+
let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 48) || false;
1901+
if (optional === null) optional = false;
19001902
const typeParameter = deserializeBoxTSTypeParameter(pos + 8);
19011903
return {
19021904
type: 'TSMappedType',
19031905
start: deserializeU32(pos),
19041906
end: deserializeU32(pos + 4),
19051907
nameType: deserializeOptionTSType(pos + 16),
19061908
typeAnnotation: deserializeOptionTSType(pos + 32),
1907-
optional: deserializeOptionTSMappedTypeModifierOperator(pos + 48),
1909+
optional,
19081910
readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 49),
19091911
key: typeParameter.name,
19101912
constraint: typeParameter.constraint,

napi/parser/generated/deserialize/ts.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2049,14 +2049,16 @@ function deserializeTSConstructorType(pos) {
20492049
}
20502050

20512051
function deserializeTSMappedType(pos) {
2052+
let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 48) || false;
2053+
if (optional === null) optional = false;
20522054
const typeParameter = deserializeBoxTSTypeParameter(pos + 8);
20532055
return {
20542056
type: 'TSMappedType',
20552057
start: deserializeU32(pos),
20562058
end: deserializeU32(pos + 4),
20572059
nameType: deserializeOptionTSType(pos + 16),
20582060
typeAnnotation: deserializeOptionTSType(pos + 32),
2059-
optional: deserializeOptionTSMappedTypeModifierOperator(pos + 48),
2061+
optional,
20602062
readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 49),
20612063
key: typeParameter.name,
20622064
constraint: typeParameter.constraint,

npm/oxc-types/types.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,7 @@ export interface TSMappedType extends Span {
13751375
type: 'TSMappedType';
13761376
nameType: TSType | null;
13771377
typeAnnotation: TSType | null;
1378-
optional: TSMappedTypeModifierOperator | null;
1378+
optional: TSMappedTypeModifierOperator | false;
13791379
readonly: TSMappedTypeModifierOperator | null;
13801380
key: TSTypeParameter['name'];
13811381
constraint: TSTypeParameter['constraint'];

0 commit comments

Comments
 (0)