Skip to content

Commit 1110399

Browse files
committed
improve type inference for + operator
1 parent 6f65df9 commit 1110399

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed

packages/babel-helper-define-polyfill-provider/src/utils.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,24 @@ export function resolveSource(obj: NodePath): {
180180
) {
181181
return { id: "Number", placement: "prototype" };
182182
}
183-
// + is ambiguous (string or number), so we can't determine the type
183+
// + depends on operand types: string wins, otherwise number or bigint
184+
if (operator === "+") {
185+
const left = resolveSource(
186+
(path as NodePath<t.BinaryExpression>).get("left"),
187+
);
188+
const right = resolveSource(
189+
(path as NodePath<t.BinaryExpression>).get("right"),
190+
);
191+
if (left.id === "String" || right.id === "String") {
192+
return { id: "String", placement: "prototype" };
193+
}
194+
if (left.id === "Number" && right.id === "Number") {
195+
return { id: "Number", placement: "prototype" };
196+
}
197+
if (left.id === "BigInt" && right.id === "BigInt") {
198+
return { id: "BigInt", placement: "prototype" };
199+
}
200+
}
184201
return { id: null, placement: null };
185202
}
186203
// (a, b, c) -> the result is the last expression

packages/babel-helper-define-polyfill-provider/test/descriptors.js

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,91 @@ describe("descriptors", () => {
437437
});
438438
});
439439

440-
it("instance property - addition is ambiguous", () => {
441-
const [desc] = getDescriptor("var a = 1, b = 2; (a + b).foo;", "property");
440+
it("instance property - addition of two numbers produces number", () => {
441+
const [desc] = getDescriptor("(1 + 2).toFixed;");
442+
443+
expect(desc).toEqual({
444+
kind: "property",
445+
object: "Number",
446+
key: "toFixed",
447+
placement: "prototype",
448+
});
449+
});
450+
451+
it("instance property - addition with string produces string", () => {
452+
const [desc] = getDescriptor('("a" + 1).includes;');
453+
454+
expect(desc).toEqual({
455+
kind: "property",
456+
object: "String",
457+
key: "includes",
458+
placement: "prototype",
459+
});
460+
});
461+
462+
it("instance property - addition string on right produces string", () => {
463+
const [desc] = getDescriptor('(1 + "b").includes;');
464+
465+
expect(desc).toEqual({
466+
kind: "property",
467+
object: "String",
468+
key: "includes",
469+
placement: "prototype",
470+
});
471+
});
472+
473+
it("instance property - addition of two strings produces string", () => {
474+
const [desc] = getDescriptor('("a" + "b").includes;');
475+
476+
expect(desc).toEqual({
477+
kind: "property",
478+
object: "String",
479+
key: "includes",
480+
placement: "prototype",
481+
});
482+
});
483+
484+
it("instance property - addition of template literal and number produces string", () => {
485+
const [desc] = getDescriptor("(`a` + 1).includes;");
486+
487+
expect(desc).toEqual({
488+
kind: "property",
489+
object: "String",
490+
key: "includes",
491+
placement: "prototype",
492+
});
493+
});
494+
495+
it("instance property - addition of two bigints produces bigint", () => {
496+
const [desc] = getDescriptor("(1n + 2n).toString;");
497+
498+
expect(desc).toEqual({
499+
kind: "property",
500+
object: "BigInt",
501+
key: "toString",
502+
placement: "prototype",
503+
});
504+
});
505+
506+
it("instance property - addition of number variables produces number", () => {
507+
const [desc] = getDescriptor(
508+
"const a = 1, b = 2; (a + b).toFixed;",
509+
"property",
510+
);
511+
512+
expect(desc).toEqual({
513+
kind: "property",
514+
object: "Number",
515+
key: "toFixed",
516+
placement: "prototype",
517+
});
518+
});
519+
520+
it("instance property - addition with unknown operands is ambiguous", () => {
521+
const [desc] = getDescriptor(
522+
"var a; var b; (a + b).foo;",
523+
"property",
524+
);
442525

443526
expect(desc).toEqual({
444527
kind: "property",

0 commit comments

Comments
 (0)