Enforce identical enum values in compatibility checks (#55924)

This commit is contained in:
Daniel Rosenwasser 2023-12-20 13:52:11 -08:00 committed by GitHub
parent 63babdf7da
commit 93e6b9da0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1108 additions and 27 deletions

View File

@ -20883,12 +20883,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return !!(entry & RelationComparisonResult.Succeeded);
}
const targetEnumType = getTypeOfSymbol(targetSymbol);
for (const property of getPropertiesOfType(getTypeOfSymbol(sourceSymbol))) {
if (property.flags & SymbolFlags.EnumMember) {
const targetProperty = getPropertyOfType(targetEnumType, property.escapedName);
for (const sourceProperty of getPropertiesOfType(getTypeOfSymbol(sourceSymbol))) {
if (sourceProperty.flags & SymbolFlags.EnumMember) {
const targetProperty = getPropertyOfType(targetEnumType, sourceProperty.escapedName);
if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) {
if (errorReporter) {
errorReporter(Diagnostics.Property_0_is_missing_in_type_1, symbolName(property), typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
errorReporter(Diagnostics.Property_0_is_missing_in_type_1, symbolName(sourceProperty), typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported);
}
else {
@ -20896,6 +20896,46 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
return false;
}
const sourceValue = getEnumMemberValue(getDeclarationOfKind(sourceProperty, SyntaxKind.EnumMember)!);
const targetValue = getEnumMemberValue(getDeclarationOfKind(targetProperty, SyntaxKind.EnumMember)!);
if (sourceValue !== targetValue) {
const sourceIsString = typeof sourceValue === "string";
const targetIsString = typeof targetValue === "string";
// If we have 2 enums with *known* values that differ, they are incompatible.
if (sourceValue !== undefined && targetValue !== undefined) {
if (!errorReporter) {
enumRelation.set(id, RelationComparisonResult.Failed);
}
else {
const escapedSource = sourceIsString ? `"${escapeString(sourceValue)}"` : sourceValue;
const escapedTarget = targetIsString ? `"${escapeString(targetValue)}"` : targetValue;
errorReporter(Diagnostics.Each_declaration_of_0_1_differs_in_its_value_where_2_was_expected_but_3_was_given, symbolName(targetSymbol), symbolName(targetProperty), escapedTarget, escapedSource);
enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported);
}
return false;
}
// At this point we know that at least one of the values is 'undefined'.
// This may mean that we have an opaque member from an ambient enum declaration,
// or that we were not able to calculate it (which is basically an error).
//
// Either way, we can assume that it's numeric.
// If the other is a string, we have a mismatch in types.
if (sourceIsString || targetIsString) {
if (!errorReporter) {
enumRelation.set(id, RelationComparisonResult.Failed);
}
else {
const knownStringValue = sourceValue ?? targetValue;
Debug.assert(typeof knownStringValue === "string");
const escapedValue = `"${escapeString(knownStringValue)}"`;
errorReporter(Diagnostics.One_value_of_0_1_is_the_string_2_and_the_other_is_assumed_to_be_an_unknown_numeric_value, symbolName(targetSymbol), symbolName(targetProperty), escapedValue);
enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported);
}
return false;
}
}
}
}
enumRelation.set(id, RelationComparisonResult.Succeeded);

View File

@ -4176,6 +4176,14 @@
"category": "Error",
"code": 4124
},
"Each declaration of '{0}.{1}' differs in its value, where '{2}' was expected but '{3}' was given.": {
"category": "Error",
"code": 4125
},
"One value of '{0}.{1}' is the string '{2}', and the other is assumed to be an unknown numeric value.": {
"category": "Error",
"code": 4126
},
"The current host does not support the '{0}' option.": {
"category": "Error",

View File

@ -916,6 +916,7 @@ export const enum JsxFlags {
// dprint-ignore
/** @internal */
export const enum RelationComparisonResult {
None = 0,
Succeeded = 1 << 0, // Should be truthy
Failed = 1 << 1,
Reported = 1 << 2,

View File

@ -1,20 +1,26 @@
enumAssignmentCompat3.ts(68,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'.
Property 'd' is missing in type 'First.E'.
enumAssignmentCompat3.ts(70,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'.
Property 'd' is missing in type 'First.E'.
Each declaration of 'E.c' differs in its value, where '2' was expected but '0' was given.
enumAssignmentCompat3.ts(71,1): error TS2322: Type 'Nope' is not assignable to type 'E'.
enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Decl.E' is not assignable to type 'First.E'.
Each declaration of 'E.c' differs in its value, where '2' was expected but '3' was given.
enumAssignmentCompat3.ts(75,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'.
Property 'c' is missing in type 'Ab.E'.
enumAssignmentCompat3.ts(76,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'.
Property 'a' is missing in type 'Cd.E'.
enumAssignmentCompat3.ts(77,1): error TS2322: Type 'E' is not assignable to type 'Nope'.
enumAssignmentCompat3.ts(78,1): error TS2322: Type 'First.E' is not assignable to type 'Decl.E'.
Each declaration of 'E.c' differs in its value, where '3' was expected but '2' was given.
enumAssignmentCompat3.ts(82,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'.
enumAssignmentCompat3.ts(83,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'.
enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'.
Property 'd' is missing in type 'First.E'.
Each declaration of 'E.c' differs in its value, where '2' was expected but '3' was given.
enumAssignmentCompat3.ts(87,1): error TS2322: Type 'First.E' is not assignable to type 'Merged.E'.
Each declaration of 'E.c' differs in its value, where '3' was expected but '2' was given.
==== enumAssignmentCompat3.ts (9 errors) ====
==== enumAssignmentCompat3.ts (12 errors) ====
namespace First {
export enum E {
a, b, c,
@ -90,11 +96,14 @@ enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable
abc = secondCd; // missing 'd'
~~~
!!! error TS2322: Type 'Cd.E' is not assignable to type 'First.E'.
!!! error TS2322: Property 'd' is missing in type 'First.E'.
!!! error TS2322: Each declaration of 'E.c' differs in its value, where '2' was expected but '0' was given.
abc = nope; // nope!
~~~
!!! error TS2322: Type 'Nope' is not assignable to type 'E'.
abc = decl; // ok
abc = decl; // bad - value of 'c' differs between these enums
~~~
!!! error TS2322: Type 'Decl.E' is not assignable to type 'First.E'.
!!! error TS2322: Each declaration of 'E.c' differs in its value, where '2' was expected but '3' was given.
secondAbc = abc; // ok
secondAbcd = abc; // ok
secondAb = abc; // missing 'c'
@ -108,7 +117,10 @@ enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable
nope = abc; // nope!
~~~~
!!! error TS2322: Type 'E' is not assignable to type 'Nope'.
decl = abc; // ok
decl = abc; // bad - value of 'c' differs between these enums
~~~~
!!! error TS2322: Type 'First.E' is not assignable to type 'Decl.E'.
!!! error TS2322: Each declaration of 'E.c' differs in its value, where '3' was expected but '2' was given.
// const is only assignable to itself
k = k;
@ -123,7 +135,10 @@ enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable
abc = merged; // missing 'd'
~~~
!!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'.
!!! error TS2322: Property 'd' is missing in type 'First.E'.
merged = abc; // ok
!!! error TS2322: Each declaration of 'E.c' differs in its value, where '2' was expected but '3' was given.
merged = abc; // bad - value of 'c' differs between these enums
~~~~~~
!!! error TS2322: Type 'First.E' is not assignable to type 'Merged.E'.
!!! error TS2322: Each declaration of 'E.c' differs in its value, where '3' was expected but '2' was given.
abc = merged2; // ok
merged2 = abc; // ok

View File

@ -72,13 +72,13 @@ abc = secondAbcd; // missing 'd'
abc = secondAb; // ok
abc = secondCd; // missing 'd'
abc = nope; // nope!
abc = decl; // ok
abc = decl; // bad - value of 'c' differs between these enums
secondAbc = abc; // ok
secondAbcd = abc; // ok
secondAb = abc; // missing 'c'
secondCd = abc; // missing 'a' and 'b'
nope = abc; // nope!
decl = abc; // ok
decl = abc; // bad - value of 'c' differs between these enums
// const is only assignable to itself
k = k;
@ -87,7 +87,7 @@ k = abc;
// merged enums compare all their members
abc = merged; // missing 'd'
merged = abc; // ok
merged = abc; // bad - value of 'c' differs between these enums
abc = merged2; // ok
merged2 = abc; // ok
@ -184,19 +184,19 @@ abc = secondAbcd; // missing 'd'
abc = secondAb; // ok
abc = secondCd; // missing 'd'
abc = nope; // nope!
abc = decl; // ok
abc = decl; // bad - value of 'c' differs between these enums
secondAbc = abc; // ok
secondAbcd = abc; // ok
secondAb = abc; // missing 'c'
secondCd = abc; // missing 'a' and 'b'
nope = abc; // nope!
decl = abc; // ok
decl = abc; // bad - value of 'c' differs between these enums
// const is only assignable to itself
k = k;
abc = k; // error
k = abc;
// merged enums compare all their members
abc = merged; // missing 'd'
merged = abc; // ok
merged = abc; // bad - value of 'c' differs between these enums
abc = merged2; // ok
merged2 = abc; // ok

View File

@ -200,7 +200,7 @@ abc = nope; // nope!
>abc : Symbol(abc, Decl(enumAssignmentCompat3.ts, 56, 3))
>nope : Symbol(nope, Decl(enumAssignmentCompat3.ts, 61, 3))
abc = decl; // ok
abc = decl; // bad - value of 'c' differs between these enums
>abc : Symbol(abc, Decl(enumAssignmentCompat3.ts, 56, 3))
>decl : Symbol(decl, Decl(enumAssignmentCompat3.ts, 63, 3))
@ -224,7 +224,7 @@ nope = abc; // nope!
>nope : Symbol(nope, Decl(enumAssignmentCompat3.ts, 61, 3))
>abc : Symbol(abc, Decl(enumAssignmentCompat3.ts, 56, 3))
decl = abc; // ok
decl = abc; // bad - value of 'c' differs between these enums
>decl : Symbol(decl, Decl(enumAssignmentCompat3.ts, 63, 3))
>abc : Symbol(abc, Decl(enumAssignmentCompat3.ts, 56, 3))
@ -246,7 +246,7 @@ abc = merged; // missing 'd'
>abc : Symbol(abc, Decl(enumAssignmentCompat3.ts, 56, 3))
>merged : Symbol(merged, Decl(enumAssignmentCompat3.ts, 64, 3))
merged = abc; // ok
merged = abc; // bad - value of 'c' differs between these enums
>merged : Symbol(merged, Decl(enumAssignmentCompat3.ts, 64, 3))
>abc : Symbol(abc, Decl(enumAssignmentCompat3.ts, 56, 3))

View File

@ -196,7 +196,7 @@ abc = nope; // nope!
>abc : First.E
>nope : Abc.Nope
abc = decl; // ok
abc = decl; // bad - value of 'c' differs between these enums
>abc = decl : Decl.E
>abc : First.E
>decl : Decl.E
@ -226,7 +226,7 @@ nope = abc; // nope!
>nope : Abc.Nope
>abc : First.E
decl = abc; // ok
decl = abc; // bad - value of 'c' differs between these enums
>decl = abc : First.E
>decl : Decl.E
>abc : First.E
@ -253,7 +253,7 @@ abc = merged; // missing 'd'
>abc : First.E
>merged : Merged.E
merged = abc; // ok
merged = abc; // bad - value of 'c' differs between these enums
>merged = abc : First.E
>merged : Merged.E
>abc : First.E

View File

@ -0,0 +1,115 @@
f.ts(37,5): error TS2322: Type 'strings.DiagnosticCategory' is not assignable to type 'numerics.DiagnosticCategory'.
Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '0' was expected but '"Warning"' was given.
f.ts(38,5): error TS2322: Type 'numerics.DiagnosticCategory' is not assignable to type 'strings.DiagnosticCategory'.
Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '"Warning"' was expected but '0' was given.
f.ts(42,5): error TS2322: Type 'DiagnosticCategory' is not assignable to type 'DiagnosticCategory2'.
f.ts(43,5): error TS2322: Type 'DiagnosticCategory2' is not assignable to type 'DiagnosticCategory'.
f.ts(52,5): error TS2322: Type 'ambients.DiagnosticCategory' is not assignable to type 'strings.DiagnosticCategory'.
One value of 'DiagnosticCategory.Warning' is the string '"Warning"', and the other is assumed to be an unknown numeric value.
f.ts(53,5): error TS2322: Type 'strings.DiagnosticCategory' is not assignable to type 'ambients.DiagnosticCategory'.
One value of 'DiagnosticCategory.Warning' is the string '"Warning"', and the other is assumed to be an unknown numeric value.
f.ts(73,9): error TS2322: Type 'DiagnosticCategory' is not assignable to type 'import("f").DiagnosticCategory'.
Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '0' was expected but '"Warning"' was given.
f.ts(74,9): error TS2322: Type 'import("f").DiagnosticCategory' is not assignable to type 'DiagnosticCategory'.
Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '"Warning"' was expected but '0' was given.
==== f.ts (8 errors) ====
// @filename a.ts
namespace numerics {
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
export enum DiagnosticCategory2 {
Warning,
Error,
Suggestion,
Message,
}
}
namespace strings {
export enum DiagnosticCategory {
Warning = "Warning",
Error = "Error",
Suggestion = "Suggestion",
Message = "Message",
}
}
declare namespace ambients {
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
}
function f(x: numerics.DiagnosticCategory, y: strings.DiagnosticCategory) {
x = y;
~
!!! error TS2322: Type 'strings.DiagnosticCategory' is not assignable to type 'numerics.DiagnosticCategory'.
!!! error TS2322: Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '0' was expected but '"Warning"' was given.
y = x;
~
!!! error TS2322: Type 'numerics.DiagnosticCategory' is not assignable to type 'strings.DiagnosticCategory'.
!!! error TS2322: Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '"Warning"' was expected but '0' was given.
}
function g(x: numerics.DiagnosticCategory2, y: strings.DiagnosticCategory) {
x = y;
~
!!! error TS2322: Type 'DiagnosticCategory' is not assignable to type 'DiagnosticCategory2'.
y = x;
~
!!! error TS2322: Type 'DiagnosticCategory2' is not assignable to type 'DiagnosticCategory'.
}
function h(x: numerics.DiagnosticCategory, y: ambients.DiagnosticCategory) {
x = y;
y = x;
}
function i(x: strings.DiagnosticCategory, y: ambients.DiagnosticCategory) {
x = y;
~
!!! error TS2322: Type 'ambients.DiagnosticCategory' is not assignable to type 'strings.DiagnosticCategory'.
!!! error TS2322: One value of 'DiagnosticCategory.Warning' is the string '"Warning"', and the other is assumed to be an unknown numeric value.
y = x;
~
!!! error TS2322: Type 'strings.DiagnosticCategory' is not assignable to type 'ambients.DiagnosticCategory'.
!!! error TS2322: One value of 'DiagnosticCategory.Warning' is the string '"Warning"', and the other is assumed to be an unknown numeric value.
}
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
export let x: DiagnosticCategory;
(() => {
enum DiagnosticCategory {
Warning = "Warning",
Error = "Error",
Suggestion = "Suggestion",
Message = "Message",
}
function f(y: DiagnosticCategory) {
x = y;
~
!!! error TS2322: Type 'DiagnosticCategory' is not assignable to type 'import("f").DiagnosticCategory'.
!!! error TS2322: Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '0' was expected but '"Warning"' was given.
y = x;
~
!!! error TS2322: Type 'import("f").DiagnosticCategory' is not assignable to type 'DiagnosticCategory'.
!!! error TS2322: Each declaration of 'DiagnosticCategory.Warning' differs in its value, where '"Warning"' was expected but '0' was given.
}
})()

View File

@ -0,0 +1,148 @@
//// [tests/cases/compiler/enumAssignmentCompat6.ts] ////
//// [f.ts]
// @filename a.ts
namespace numerics {
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
export enum DiagnosticCategory2 {
Warning,
Error,
Suggestion,
Message,
}
}
namespace strings {
export enum DiagnosticCategory {
Warning = "Warning",
Error = "Error",
Suggestion = "Suggestion",
Message = "Message",
}
}
declare namespace ambients {
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
}
function f(x: numerics.DiagnosticCategory, y: strings.DiagnosticCategory) {
x = y;
y = x;
}
function g(x: numerics.DiagnosticCategory2, y: strings.DiagnosticCategory) {
x = y;
y = x;
}
function h(x: numerics.DiagnosticCategory, y: ambients.DiagnosticCategory) {
x = y;
y = x;
}
function i(x: strings.DiagnosticCategory, y: ambients.DiagnosticCategory) {
x = y;
y = x;
}
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
export let x: DiagnosticCategory;
(() => {
enum DiagnosticCategory {
Warning = "Warning",
Error = "Error",
Suggestion = "Suggestion",
Message = "Message",
}
function f(y: DiagnosticCategory) {
x = y;
y = x;
}
})()
//// [f.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.x = exports.DiagnosticCategory = void 0;
// @filename a.ts
var numerics;
(function (numerics) {
var DiagnosticCategory;
(function (DiagnosticCategory) {
DiagnosticCategory[DiagnosticCategory["Warning"] = 0] = "Warning";
DiagnosticCategory[DiagnosticCategory["Error"] = 1] = "Error";
DiagnosticCategory[DiagnosticCategory["Suggestion"] = 2] = "Suggestion";
DiagnosticCategory[DiagnosticCategory["Message"] = 3] = "Message";
})(DiagnosticCategory = numerics.DiagnosticCategory || (numerics.DiagnosticCategory = {}));
var DiagnosticCategory2;
(function (DiagnosticCategory2) {
DiagnosticCategory2[DiagnosticCategory2["Warning"] = 0] = "Warning";
DiagnosticCategory2[DiagnosticCategory2["Error"] = 1] = "Error";
DiagnosticCategory2[DiagnosticCategory2["Suggestion"] = 2] = "Suggestion";
DiagnosticCategory2[DiagnosticCategory2["Message"] = 3] = "Message";
})(DiagnosticCategory2 = numerics.DiagnosticCategory2 || (numerics.DiagnosticCategory2 = {}));
})(numerics || (numerics = {}));
var strings;
(function (strings) {
var DiagnosticCategory;
(function (DiagnosticCategory) {
DiagnosticCategory["Warning"] = "Warning";
DiagnosticCategory["Error"] = "Error";
DiagnosticCategory["Suggestion"] = "Suggestion";
DiagnosticCategory["Message"] = "Message";
})(DiagnosticCategory = strings.DiagnosticCategory || (strings.DiagnosticCategory = {}));
})(strings || (strings = {}));
function f(x, y) {
x = y;
y = x;
}
function g(x, y) {
x = y;
y = x;
}
function h(x, y) {
x = y;
y = x;
}
function i(x, y) {
x = y;
y = x;
}
var DiagnosticCategory;
(function (DiagnosticCategory) {
DiagnosticCategory[DiagnosticCategory["Warning"] = 0] = "Warning";
DiagnosticCategory[DiagnosticCategory["Error"] = 1] = "Error";
DiagnosticCategory[DiagnosticCategory["Suggestion"] = 2] = "Suggestion";
DiagnosticCategory[DiagnosticCategory["Message"] = 3] = "Message";
})(DiagnosticCategory || (exports.DiagnosticCategory = DiagnosticCategory = {}));
(function () {
var DiagnosticCategory;
(function (DiagnosticCategory) {
DiagnosticCategory["Warning"] = "Warning";
DiagnosticCategory["Error"] = "Error";
DiagnosticCategory["Suggestion"] = "Suggestion";
DiagnosticCategory["Message"] = "Message";
})(DiagnosticCategory || (DiagnosticCategory = {}));
function f(y) {
exports.x = y;
y = exports.x;
}
})();

View File

@ -0,0 +1,202 @@
//// [tests/cases/compiler/enumAssignmentCompat6.ts] ////
=== f.ts ===
// @filename a.ts
namespace numerics {
>numerics : Symbol(numerics, Decl(f.ts, 0, 0))
export enum DiagnosticCategory {
>DiagnosticCategory : Symbol(DiagnosticCategory, Decl(f.ts, 1, 20))
Warning,
>Warning : Symbol(DiagnosticCategory.Warning, Decl(f.ts, 2, 36))
Error,
>Error : Symbol(DiagnosticCategory.Error, Decl(f.ts, 3, 16))
Suggestion,
>Suggestion : Symbol(DiagnosticCategory.Suggestion, Decl(f.ts, 4, 14))
Message,
>Message : Symbol(DiagnosticCategory.Message, Decl(f.ts, 5, 19))
}
export enum DiagnosticCategory2 {
>DiagnosticCategory2 : Symbol(DiagnosticCategory2, Decl(f.ts, 7, 5))
Warning,
>Warning : Symbol(DiagnosticCategory2.Warning, Decl(f.ts, 9, 37))
Error,
>Error : Symbol(DiagnosticCategory2.Error, Decl(f.ts, 10, 16))
Suggestion,
>Suggestion : Symbol(DiagnosticCategory2.Suggestion, Decl(f.ts, 11, 14))
Message,
>Message : Symbol(DiagnosticCategory2.Message, Decl(f.ts, 12, 19))
}
}
namespace strings {
>strings : Symbol(strings, Decl(f.ts, 15, 1))
export enum DiagnosticCategory {
>DiagnosticCategory : Symbol(DiagnosticCategory, Decl(f.ts, 17, 19))
Warning = "Warning",
>Warning : Symbol(DiagnosticCategory.Warning, Decl(f.ts, 18, 36))
Error = "Error",
>Error : Symbol(DiagnosticCategory.Error, Decl(f.ts, 19, 28))
Suggestion = "Suggestion",
>Suggestion : Symbol(DiagnosticCategory.Suggestion, Decl(f.ts, 20, 24))
Message = "Message",
>Message : Symbol(DiagnosticCategory.Message, Decl(f.ts, 21, 34))
}
}
declare namespace ambients {
>ambients : Symbol(ambients, Decl(f.ts, 24, 1))
export enum DiagnosticCategory {
>DiagnosticCategory : Symbol(DiagnosticCategory, Decl(f.ts, 26, 28))
Warning,
>Warning : Symbol(DiagnosticCategory.Warning, Decl(f.ts, 27, 36))
Error,
>Error : Symbol(DiagnosticCategory.Error, Decl(f.ts, 28, 16))
Suggestion,
>Suggestion : Symbol(DiagnosticCategory.Suggestion, Decl(f.ts, 29, 14))
Message,
>Message : Symbol(DiagnosticCategory.Message, Decl(f.ts, 30, 19))
}
}
function f(x: numerics.DiagnosticCategory, y: strings.DiagnosticCategory) {
>f : Symbol(f, Decl(f.ts, 33, 1))
>x : Symbol(x, Decl(f.ts, 35, 11))
>numerics : Symbol(numerics, Decl(f.ts, 0, 0))
>DiagnosticCategory : Symbol(numerics.DiagnosticCategory, Decl(f.ts, 1, 20))
>y : Symbol(y, Decl(f.ts, 35, 42))
>strings : Symbol(strings, Decl(f.ts, 15, 1))
>DiagnosticCategory : Symbol(strings.DiagnosticCategory, Decl(f.ts, 17, 19))
x = y;
>x : Symbol(x, Decl(f.ts, 35, 11))
>y : Symbol(y, Decl(f.ts, 35, 42))
y = x;
>y : Symbol(y, Decl(f.ts, 35, 42))
>x : Symbol(x, Decl(f.ts, 35, 11))
}
function g(x: numerics.DiagnosticCategory2, y: strings.DiagnosticCategory) {
>g : Symbol(g, Decl(f.ts, 38, 1))
>x : Symbol(x, Decl(f.ts, 40, 11))
>numerics : Symbol(numerics, Decl(f.ts, 0, 0))
>DiagnosticCategory2 : Symbol(numerics.DiagnosticCategory2, Decl(f.ts, 7, 5))
>y : Symbol(y, Decl(f.ts, 40, 43))
>strings : Symbol(strings, Decl(f.ts, 15, 1))
>DiagnosticCategory : Symbol(strings.DiagnosticCategory, Decl(f.ts, 17, 19))
x = y;
>x : Symbol(x, Decl(f.ts, 40, 11))
>y : Symbol(y, Decl(f.ts, 40, 43))
y = x;
>y : Symbol(y, Decl(f.ts, 40, 43))
>x : Symbol(x, Decl(f.ts, 40, 11))
}
function h(x: numerics.DiagnosticCategory, y: ambients.DiagnosticCategory) {
>h : Symbol(h, Decl(f.ts, 43, 1))
>x : Symbol(x, Decl(f.ts, 45, 11))
>numerics : Symbol(numerics, Decl(f.ts, 0, 0))
>DiagnosticCategory : Symbol(numerics.DiagnosticCategory, Decl(f.ts, 1, 20))
>y : Symbol(y, Decl(f.ts, 45, 42))
>ambients : Symbol(ambients, Decl(f.ts, 24, 1))
>DiagnosticCategory : Symbol(ambients.DiagnosticCategory, Decl(f.ts, 26, 28))
x = y;
>x : Symbol(x, Decl(f.ts, 45, 11))
>y : Symbol(y, Decl(f.ts, 45, 42))
y = x;
>y : Symbol(y, Decl(f.ts, 45, 42))
>x : Symbol(x, Decl(f.ts, 45, 11))
}
function i(x: strings.DiagnosticCategory, y: ambients.DiagnosticCategory) {
>i : Symbol(i, Decl(f.ts, 48, 1))
>x : Symbol(x, Decl(f.ts, 50, 11))
>strings : Symbol(strings, Decl(f.ts, 15, 1))
>DiagnosticCategory : Symbol(strings.DiagnosticCategory, Decl(f.ts, 17, 19))
>y : Symbol(y, Decl(f.ts, 50, 41))
>ambients : Symbol(ambients, Decl(f.ts, 24, 1))
>DiagnosticCategory : Symbol(ambients.DiagnosticCategory, Decl(f.ts, 26, 28))
x = y;
>x : Symbol(x, Decl(f.ts, 50, 11))
>y : Symbol(y, Decl(f.ts, 50, 41))
y = x;
>y : Symbol(y, Decl(f.ts, 50, 41))
>x : Symbol(x, Decl(f.ts, 50, 11))
}
export enum DiagnosticCategory {
>DiagnosticCategory : Symbol(DiagnosticCategory, Decl(f.ts, 53, 1))
Warning,
>Warning : Symbol(DiagnosticCategory.Warning, Decl(f.ts, 55, 32))
Error,
>Error : Symbol(DiagnosticCategory.Error, Decl(f.ts, 56, 12))
Suggestion,
>Suggestion : Symbol(DiagnosticCategory.Suggestion, Decl(f.ts, 57, 10))
Message,
>Message : Symbol(DiagnosticCategory.Message, Decl(f.ts, 58, 15))
}
export let x: DiagnosticCategory;
>x : Symbol(x, Decl(f.ts, 62, 10))
>DiagnosticCategory : Symbol(DiagnosticCategory, Decl(f.ts, 53, 1))
(() => {
enum DiagnosticCategory {
>DiagnosticCategory : Symbol(DiagnosticCategory, Decl(f.ts, 64, 8))
Warning = "Warning",
>Warning : Symbol(DiagnosticCategory.Warning, Decl(f.ts, 65, 29))
Error = "Error",
>Error : Symbol(DiagnosticCategory.Error, Decl(f.ts, 66, 28))
Suggestion = "Suggestion",
>Suggestion : Symbol(DiagnosticCategory.Suggestion, Decl(f.ts, 67, 24))
Message = "Message",
>Message : Symbol(DiagnosticCategory.Message, Decl(f.ts, 68, 34))
}
function f(y: DiagnosticCategory) {
>f : Symbol(f, Decl(f.ts, 70, 5))
>y : Symbol(y, Decl(f.ts, 71, 15))
>DiagnosticCategory : Symbol(DiagnosticCategory, Decl(f.ts, 64, 8))
x = y;
>x : Symbol(x, Decl(f.ts, 62, 10))
>y : Symbol(y, Decl(f.ts, 71, 15))
y = x;
>y : Symbol(y, Decl(f.ts, 71, 15))
>x : Symbol(x, Decl(f.ts, 62, 10))
}
})()

View File

@ -0,0 +1,214 @@
//// [tests/cases/compiler/enumAssignmentCompat6.ts] ////
=== f.ts ===
// @filename a.ts
namespace numerics {
>numerics : typeof numerics
export enum DiagnosticCategory {
>DiagnosticCategory : DiagnosticCategory
Warning,
>Warning : DiagnosticCategory.Warning
Error,
>Error : DiagnosticCategory.Error
Suggestion,
>Suggestion : DiagnosticCategory.Suggestion
Message,
>Message : DiagnosticCategory.Message
}
export enum DiagnosticCategory2 {
>DiagnosticCategory2 : DiagnosticCategory2
Warning,
>Warning : DiagnosticCategory2.Warning
Error,
>Error : DiagnosticCategory2.Error
Suggestion,
>Suggestion : DiagnosticCategory2.Suggestion
Message,
>Message : DiagnosticCategory2.Message
}
}
namespace strings {
>strings : typeof strings
export enum DiagnosticCategory {
>DiagnosticCategory : DiagnosticCategory
Warning = "Warning",
>Warning : DiagnosticCategory.Warning
>"Warning" : "Warning"
Error = "Error",
>Error : DiagnosticCategory.Error
>"Error" : "Error"
Suggestion = "Suggestion",
>Suggestion : DiagnosticCategory.Suggestion
>"Suggestion" : "Suggestion"
Message = "Message",
>Message : DiagnosticCategory.Message
>"Message" : "Message"
}
}
declare namespace ambients {
>ambients : typeof ambients
export enum DiagnosticCategory {
>DiagnosticCategory : DiagnosticCategory
Warning,
>Warning : DiagnosticCategory.Warning
Error,
>Error : DiagnosticCategory.Error
Suggestion,
>Suggestion : DiagnosticCategory.Suggestion
Message,
>Message : DiagnosticCategory.Message
}
}
function f(x: numerics.DiagnosticCategory, y: strings.DiagnosticCategory) {
>f : (x: numerics.DiagnosticCategory, y: strings.DiagnosticCategory) => void
>x : numerics.DiagnosticCategory
>numerics : any
>y : strings.DiagnosticCategory
>strings : any
x = y;
>x = y : strings.DiagnosticCategory
>x : numerics.DiagnosticCategory
>y : strings.DiagnosticCategory
y = x;
>y = x : numerics.DiagnosticCategory
>y : strings.DiagnosticCategory
>x : numerics.DiagnosticCategory
}
function g(x: numerics.DiagnosticCategory2, y: strings.DiagnosticCategory) {
>g : (x: numerics.DiagnosticCategory2, y: strings.DiagnosticCategory) => void
>x : numerics.DiagnosticCategory2
>numerics : any
>y : strings.DiagnosticCategory
>strings : any
x = y;
>x = y : strings.DiagnosticCategory
>x : numerics.DiagnosticCategory2
>y : strings.DiagnosticCategory
y = x;
>y = x : numerics.DiagnosticCategory2
>y : strings.DiagnosticCategory
>x : numerics.DiagnosticCategory2
}
function h(x: numerics.DiagnosticCategory, y: ambients.DiagnosticCategory) {
>h : (x: numerics.DiagnosticCategory, y: ambients.DiagnosticCategory) => void
>x : numerics.DiagnosticCategory
>numerics : any
>y : ambients.DiagnosticCategory
>ambients : any
x = y;
>x = y : ambients.DiagnosticCategory
>x : numerics.DiagnosticCategory
>y : ambients.DiagnosticCategory
y = x;
>y = x : numerics.DiagnosticCategory
>y : ambients.DiagnosticCategory
>x : numerics.DiagnosticCategory
}
function i(x: strings.DiagnosticCategory, y: ambients.DiagnosticCategory) {
>i : (x: strings.DiagnosticCategory, y: ambients.DiagnosticCategory) => void
>x : strings.DiagnosticCategory
>strings : any
>y : ambients.DiagnosticCategory
>ambients : any
x = y;
>x = y : ambients.DiagnosticCategory
>x : strings.DiagnosticCategory
>y : ambients.DiagnosticCategory
y = x;
>y = x : strings.DiagnosticCategory
>y : ambients.DiagnosticCategory
>x : strings.DiagnosticCategory
}
export enum DiagnosticCategory {
>DiagnosticCategory : DiagnosticCategory
Warning,
>Warning : DiagnosticCategory.Warning
Error,
>Error : DiagnosticCategory.Error
Suggestion,
>Suggestion : DiagnosticCategory.Suggestion
Message,
>Message : DiagnosticCategory.Message
}
export let x: DiagnosticCategory;
>x : DiagnosticCategory
(() => {
>(() => { enum DiagnosticCategory { Warning = "Warning", Error = "Error", Suggestion = "Suggestion", Message = "Message", } function f(y: DiagnosticCategory) { x = y; y = x; }})() : void
>(() => { enum DiagnosticCategory { Warning = "Warning", Error = "Error", Suggestion = "Suggestion", Message = "Message", } function f(y: DiagnosticCategory) { x = y; y = x; }}) : () => void
>() => { enum DiagnosticCategory { Warning = "Warning", Error = "Error", Suggestion = "Suggestion", Message = "Message", } function f(y: DiagnosticCategory) { x = y; y = x; }} : () => void
enum DiagnosticCategory {
>DiagnosticCategory : DiagnosticCategory
Warning = "Warning",
>Warning : DiagnosticCategory.Warning
>"Warning" : "Warning"
Error = "Error",
>Error : DiagnosticCategory.Error
>"Error" : "Error"
Suggestion = "Suggestion",
>Suggestion : DiagnosticCategory.Suggestion
>"Suggestion" : "Suggestion"
Message = "Message",
>Message : DiagnosticCategory.Message
>"Message" : "Message"
}
function f(y: DiagnosticCategory) {
>f : (y: DiagnosticCategory) => void
>y : DiagnosticCategory
x = y;
>x = y : DiagnosticCategory
>x : import("f").DiagnosticCategory
>y : DiagnosticCategory
y = x;
>y = x : import("f").DiagnosticCategory
>y : DiagnosticCategory
>x : import("f").DiagnosticCategory
}
})()

View File

@ -0,0 +1,42 @@
enumAssignmentCompat7.ts(16,14): error TS2416: Property 'method' in type 'Derived' is not assignable to the same property in base type 'Base'.
Type '(param: second.E) => void' is not assignable to type '(param: first.E) => void'.
Types of parameters 'param' and 'param' are incompatible.
Type 'first.E' is not assignable to type 'second.E'.
enumAssignmentCompat7.ts(20,10): error TS2394: This overload signature is not compatible with its implementation signature.
enumAssignmentCompat7.ts(22,21): error TS2339: Property 'B' does not exist on type 'typeof E'.
==== enumAssignmentCompat7.ts (3 errors) ====
namespace first {
export enum E { A = 1 }
}
namespace second {
export enum E { A = 2 }
}
class Base {
method(param: first.E) {
}
}
class Derived extends Base {
override method(param: second.E) {
~~~~~~
!!! error TS2416: Property 'method' in type 'Derived' is not assignable to the same property in base type 'Base'.
!!! error TS2416: Type '(param: second.E) => void' is not assignable to type '(param: first.E) => void'.
!!! error TS2416: Types of parameters 'param' and 'param' are incompatible.
!!! error TS2416: Type 'first.E' is not assignable to type 'second.E'.
}
}
function overloadingFunction(): first.E
~~~~~~~~~~~~~~~~~~~
!!! error TS2394: This overload signature is not compatible with its implementation signature.
!!! related TS2750 enumAssignmentCompat7.ts:21:10: The implementation signature is declared here.
function overloadingFunction(): second.E {
return second.E.B
~
!!! error TS2339: Property 'B' does not exist on type 'typeof E'.
}

View File

@ -0,0 +1,77 @@
//// [tests/cases/compiler/enumAssignmentCompat7.ts] ////
//// [enumAssignmentCompat7.ts]
namespace first {
export enum E { A = 1 }
}
namespace second {
export enum E { A = 2 }
}
class Base {
method(param: first.E) {
}
}
class Derived extends Base {
override method(param: second.E) {
}
}
function overloadingFunction(): first.E
function overloadingFunction(): second.E {
return second.E.B
}
//// [enumAssignmentCompat7.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var first;
(function (first) {
var E;
(function (E) {
E[E["A"] = 1] = "A";
})(E = first.E || (first.E = {}));
})(first || (first = {}));
var second;
(function (second) {
var E;
(function (E) {
E[E["A"] = 2] = "A";
})(E = second.E || (second.E = {}));
})(second || (second = {}));
var Base = /** @class */ (function () {
function Base() {
}
Base.prototype.method = function (param) {
};
return Base;
}());
var Derived = /** @class */ (function (_super) {
__extends(Derived, _super);
function Derived() {
return _super !== null && _super.apply(this, arguments) || this;
}
Derived.prototype.method = function (param) {
};
return Derived;
}(Base));
function overloadingFunction() {
return second.E.B;
}

View File

@ -0,0 +1,58 @@
//// [tests/cases/compiler/enumAssignmentCompat7.ts] ////
=== enumAssignmentCompat7.ts ===
namespace first {
>first : Symbol(first, Decl(enumAssignmentCompat7.ts, 0, 0))
export enum E { A = 1 }
>E : Symbol(E, Decl(enumAssignmentCompat7.ts, 0, 17))
>A : Symbol(E.A, Decl(enumAssignmentCompat7.ts, 1, 19))
}
namespace second {
>second : Symbol(second, Decl(enumAssignmentCompat7.ts, 2, 1))
export enum E { A = 2 }
>E : Symbol(E, Decl(enumAssignmentCompat7.ts, 4, 18))
>A : Symbol(E.A, Decl(enumAssignmentCompat7.ts, 5, 19))
}
class Base {
>Base : Symbol(Base, Decl(enumAssignmentCompat7.ts, 6, 1))
method(param: first.E) {
>method : Symbol(Base.method, Decl(enumAssignmentCompat7.ts, 8, 12))
>param : Symbol(param, Decl(enumAssignmentCompat7.ts, 9, 11))
>first : Symbol(first, Decl(enumAssignmentCompat7.ts, 0, 0))
>E : Symbol(first.E, Decl(enumAssignmentCompat7.ts, 0, 17))
}
}
class Derived extends Base {
>Derived : Symbol(Derived, Decl(enumAssignmentCompat7.ts, 12, 1))
>Base : Symbol(Base, Decl(enumAssignmentCompat7.ts, 6, 1))
override method(param: second.E) {
>method : Symbol(Derived.method, Decl(enumAssignmentCompat7.ts, 14, 28))
>param : Symbol(param, Decl(enumAssignmentCompat7.ts, 15, 20))
>second : Symbol(second, Decl(enumAssignmentCompat7.ts, 2, 1))
>E : Symbol(second.E, Decl(enumAssignmentCompat7.ts, 4, 18))
}
}
function overloadingFunction(): first.E
>overloadingFunction : Symbol(overloadingFunction, Decl(enumAssignmentCompat7.ts, 17, 1), Decl(enumAssignmentCompat7.ts, 19, 39))
>first : Symbol(first, Decl(enumAssignmentCompat7.ts, 0, 0))
>E : Symbol(first.E, Decl(enumAssignmentCompat7.ts, 0, 17))
function overloadingFunction(): second.E {
>overloadingFunction : Symbol(overloadingFunction, Decl(enumAssignmentCompat7.ts, 17, 1), Decl(enumAssignmentCompat7.ts, 19, 39))
>second : Symbol(second, Decl(enumAssignmentCompat7.ts, 2, 1))
>E : Symbol(second.E, Decl(enumAssignmentCompat7.ts, 4, 18))
return second.E.B
>second.E : Symbol(second.E, Decl(enumAssignmentCompat7.ts, 4, 18))
>second : Symbol(second, Decl(enumAssignmentCompat7.ts, 2, 1))
>E : Symbol(second.E, Decl(enumAssignmentCompat7.ts, 4, 18))
}

View File

@ -0,0 +1,58 @@
//// [tests/cases/compiler/enumAssignmentCompat7.ts] ////
=== enumAssignmentCompat7.ts ===
namespace first {
>first : typeof first
export enum E { A = 1 }
>E : E
>A : E.A
>1 : 1
}
namespace second {
>second : typeof second
export enum E { A = 2 }
>E : E
>A : E.A
>2 : 2
}
class Base {
>Base : Base
method(param: first.E) {
>method : (param: first.E) => void
>param : first.E
>first : any
}
}
class Derived extends Base {
>Derived : Derived
>Base : Base
override method(param: second.E) {
>method : (param: second.E) => void
>param : second.E
>second : any
}
}
function overloadingFunction(): first.E
>overloadingFunction : () => first.E
>first : any
function overloadingFunction(): second.E {
>overloadingFunction : () => first.E
>second : any
return second.E.B
>second.E.B : any
>second.E : typeof second.E
>second : typeof second
>E : typeof second.E
>B : any
}

View File

@ -69,13 +69,13 @@ abc = secondAbcd; // missing 'd'
abc = secondAb; // ok
abc = secondCd; // missing 'd'
abc = nope; // nope!
abc = decl; // ok
abc = decl; // bad - value of 'c' differs between these enums
secondAbc = abc; // ok
secondAbcd = abc; // ok
secondAb = abc; // missing 'c'
secondCd = abc; // missing 'a' and 'b'
nope = abc; // nope!
decl = abc; // ok
decl = abc; // bad - value of 'c' differs between these enums
// const is only assignable to itself
k = k;
@ -84,6 +84,6 @@ k = abc;
// merged enums compare all their members
abc = merged; // missing 'd'
merged = abc; // ok
merged = abc; // bad - value of 'c' differs between these enums
abc = merged2; // ok
merged2 = abc; // ok

View File

@ -0,0 +1,77 @@
// @filename a.ts
namespace numerics {
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
export enum DiagnosticCategory2 {
Warning,
Error,
Suggestion,
Message,
}
}
namespace strings {
export enum DiagnosticCategory {
Warning = "Warning",
Error = "Error",
Suggestion = "Suggestion",
Message = "Message",
}
}
declare namespace ambients {
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
}
function f(x: numerics.DiagnosticCategory, y: strings.DiagnosticCategory) {
x = y;
y = x;
}
function g(x: numerics.DiagnosticCategory2, y: strings.DiagnosticCategory) {
x = y;
y = x;
}
function h(x: numerics.DiagnosticCategory, y: ambients.DiagnosticCategory) {
x = y;
y = x;
}
function i(x: strings.DiagnosticCategory, y: ambients.DiagnosticCategory) {
x = y;
y = x;
}
// @filename: f.ts
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message,
}
export let x: DiagnosticCategory;
(() => {
enum DiagnosticCategory {
Warning = "Warning",
Error = "Error",
Suggestion = "Suggestion",
Message = "Message",
}
function f(y: DiagnosticCategory) {
x = y;
y = x;
}
})()

View File

@ -0,0 +1,26 @@
// @strict: true
// @strictFunctionTypes: false
namespace first {
export enum E { A = 1 }
}
namespace second {
export enum E { A = 2 }
}
class Base {
method(param: first.E) {
}
}
class Derived extends Base {
override method(param: second.E) {
}
}
function overloadingFunction(): first.E
function overloadingFunction(): second.E {
return second.E.B
}