diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index af45b00c518..82f41bc31e6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9083,11 +9083,26 @@ namespace ts { else { // use the property's value declaration if the property is assigned inside the literal itself const objectLiteralDeclaration = source.symbol && firstOrUndefined(source.symbol.declarations); + let suggestion; if (prop.valueDeclaration && findAncestor(prop.valueDeclaration, d => d === objectLiteralDeclaration)) { - errorNode = prop.valueDeclaration; + const propDeclaration = prop.valueDeclaration as ObjectLiteralElementLike; + Debug.assertNode(propDeclaration, isObjectLiteralElementLike); + + errorNode = propDeclaration; + + if (isIdentifier(propDeclaration.name)) { + suggestion = getSuggestionForNonexistentProperty(propDeclaration.name, target); + } + } + + if (suggestion !== undefined) { + reportError(Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2, + symbolToString(prop), typeToString(target), unescapeLeadingUnderscores(suggestion)); + } + else { + reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, + symbolToString(prop), typeToString(target)); } - reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, - symbolToString(prop), typeToString(target)); } } return true; @@ -14739,8 +14754,8 @@ namespace ts { } } const suggestion = getSuggestionForNonexistentProperty(propNode, containingType); - if (suggestion) { - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion); + if (suggestion !== undefined) { + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), unescapeLeadingUnderscores(suggestion)); } else { errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType)); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 8cab1b41155..eae2e5ee336 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1359,7 +1359,7 @@ namespace ts { }; } - export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: any[]): DiagnosticMessageChain; + export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: string[]): DiagnosticMessageChain; export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain { let text = getLocaleSpecificMessage(message); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 049483fdb8f..8121f036cea 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1912,10 +1912,14 @@ "category": "Error", "code": 2560 }, - "Base class expressions cannot reference class type parameters.": { + "Object literal may only specify known properties, but '{0}' does not exist in type '{1}'. Did you mean to write '{2}'?": { "category": "Error", "code": 2561 }, + "Base class expressions cannot reference class type parameters.": { + "category": "Error", + "code": 2562 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 diff --git a/tests/baselines/reference/baseExpressionTypeParameters.errors.txt b/tests/baselines/reference/baseExpressionTypeParameters.errors.txt index 4fa8f2f6d3d..cb259e49dd2 100644 --- a/tests/baselines/reference/baseExpressionTypeParameters.errors.txt +++ b/tests/baselines/reference/baseExpressionTypeParameters.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/baseExpressionTypeParameters.ts(10,27): error TS2561: Base class expressions cannot reference class type parameters. +tests/cases/compiler/baseExpressionTypeParameters.ts(10,27): error TS2562: Base class expressions cannot reference class type parameters. ==== tests/cases/compiler/baseExpressionTypeParameters.ts (1 errors) ==== @@ -13,7 +13,7 @@ tests/cases/compiler/baseExpressionTypeParameters.ts(10,27): error TS2561: Base class Gen extends base() {} // Error, T not in scope ~ -!!! error TS2561: Base class expressions cannot reference class type parameters. +!!! error TS2562: Base class expressions cannot reference class type parameters. class Spec extends Gen {} Spec.prop; \ No newline at end of file diff --git a/tests/baselines/reference/nestedFreshLiteral.errors.txt b/tests/baselines/reference/nestedFreshLiteral.errors.txt index 6aff94ac0a6..d68b398449d 100644 --- a/tests/baselines/reference/nestedFreshLiteral.errors.txt +++ b/tests/baselines/reference/nestedFreshLiteral.errors.txt @@ -4,7 +4,7 @@ tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ nested: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'. Types of property 'prop' are incompatible. Type '{ colour: string; }' is not assignable to type 'CSSProps'. - Object literal may only specify known properties, and 'colour' does not exist in type 'CSSProps'. + Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'? ==== tests/cases/compiler/nestedFreshLiteral.ts (1 errors) ==== @@ -27,5 +27,5 @@ tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ nested: !!! error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'. !!! error TS2322: Types of property 'prop' are incompatible. !!! error TS2322: Type '{ colour: string; }' is not assignable to type 'CSSProps'. -!!! error TS2322: Object literal may only specify known properties, and 'colour' does not exist in type 'CSSProps'. +!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'? } \ No newline at end of file diff --git a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt index 98f2e30287c..0c5909dc4ed 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt +++ b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(9,18): error TS2322: Type '{ forword: string; }' is not assignable to type 'Book'. - Object literal may only specify known properties, and 'forword' does not exist in type 'Book'. + Object literal may only specify known properties, but 'forword' does not exist in type 'Book'. Did you mean to write 'foreword'? tests/cases/compiler/objectLiteralExcessProperties.ts(11,27): error TS2322: Type '{ foreward: string; }' is not assignable to type 'string | Book'. Object literal may only specify known properties, and 'foreward' does not exist in type 'string | Book'. tests/cases/compiler/objectLiteralExcessProperties.ts(13,53): error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book | Book[]'. @@ -8,9 +8,9 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(13,53): error TS2322: Type Type '{ forwards: string; }' is not assignable to type 'Book'. Object literal may only specify known properties, and 'forwards' does not exist in type 'Book'. tests/cases/compiler/objectLiteralExcessProperties.ts(15,42): error TS2322: Type '{ foreword: string; colour: string; }' is not assignable to type 'Book & Cover'. - Object literal may only specify known properties, and 'colour' does not exist in type 'Book & Cover'. + Object literal may only specify known properties, but 'colour' does not exist in type 'Book & Cover'. Did you mean to write 'color'? tests/cases/compiler/objectLiteralExcessProperties.ts(17,26): error TS2322: Type '{ foreward: string; color: string; }' is not assignable to type 'Book & Cover'. - Object literal may only specify known properties, and 'foreward' does not exist in type 'Book & Cover'. + Object literal may only specify known properties, but 'foreward' does not exist in type 'Book & Cover'. Did you mean to write 'foreword'? tests/cases/compiler/objectLiteralExcessProperties.ts(19,57): error TS2322: Type '{ foreword: string; color: string; price: number; }' is not assignable to type 'Book & Cover'. Object literal may only specify known properties, and 'price' does not exist in type 'Book & Cover'. tests/cases/compiler/objectLiteralExcessProperties.ts(21,43): error TS2322: Type '{ foreword: string; price: number; }' is not assignable to type 'Book & number'. @@ -22,7 +22,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(25,27): error TS2322: Type tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type '{ 0: { colour: string; }; }' is not assignable to type 'Indexed'. Property '0' is incompatible with index signature. Type '{ colour: string; }' is not assignable to type 'Cover'. - Object literal may only specify known properties, and 'colour' does not exist in type 'Cover'. + Object literal may only specify known properties, but 'colour' does not exist in type 'Cover'. Did you mean to write 'color'? ==== tests/cases/compiler/objectLiteralExcessProperties.ts (10 errors) ==== @@ -37,7 +37,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type var b1: Book = { forword: "oops" }; ~~~~~~~~~~~~~~~ !!! error TS2322: Type '{ forword: string; }' is not assignable to type 'Book'. -!!! error TS2322: Object literal may only specify known properties, and 'forword' does not exist in type 'Book'. +!!! error TS2322: Object literal may only specify known properties, but 'forword' does not exist in type 'Book'. Did you mean to write 'foreword'? var b2: Book | string = { foreward: "nope" }; ~~~~~~~~~~~~~~~~ @@ -55,12 +55,12 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type var b4: Book & Cover = { foreword: "hi", colour: "blue" }; ~~~~~~~~~~~~~~ !!! error TS2322: Type '{ foreword: string; colour: string; }' is not assignable to type 'Book & Cover'. -!!! error TS2322: Object literal may only specify known properties, and 'colour' does not exist in type 'Book & Cover'. +!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'Book & Cover'. Did you mean to write 'color'? var b5: Book & Cover = { foreward: "hi", color: "blue" }; ~~~~~~~~~~~~~~ !!! error TS2322: Type '{ foreward: string; color: string; }' is not assignable to type 'Book & Cover'. -!!! error TS2322: Object literal may only specify known properties, and 'foreward' does not exist in type 'Book & Cover'. +!!! error TS2322: Object literal may only specify known properties, but 'foreward' does not exist in type 'Book & Cover'. Did you mean to write 'foreword'? var b6: Book & Cover = { foreword: "hi", color: "blue", price: 10.99 }; ~~~~~~~~~~~~ @@ -93,5 +93,5 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type !!! error TS2322: Type '{ 0: { colour: string; }; }' is not assignable to type 'Indexed'. !!! error TS2322: Property '0' is incompatible with index signature. !!! error TS2322: Type '{ colour: string; }' is not assignable to type 'Cover'. -!!! error TS2322: Object literal may only specify known properties, and 'colour' does not exist in type 'Cover'. +!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'Cover'. Did you mean to write 'color'? \ No newline at end of file diff --git a/tests/baselines/reference/spellingSuggestionLeadingUnderscores01.errors.txt b/tests/baselines/reference/spellingSuggestionLeadingUnderscores01.errors.txt new file mode 100644 index 00000000000..39a4901da98 --- /dev/null +++ b/tests/baselines/reference/spellingSuggestionLeadingUnderscores01.errors.txt @@ -0,0 +1,28 @@ +tests/cases/compiler/spellingSuggestionLeadingUnderscores01.ts(6,3): error TS2551: Property '___foo' does not exist on type '{ __foo: 10; }'. Did you mean '__foo'? +tests/cases/compiler/spellingSuggestionLeadingUnderscores01.ts(14,5): error TS2322: Type '{ ___foo: number; }' is not assignable to type '{ __foo: number; }'. + Object literal may only specify known properties, but '___foo' does not exist in type '{ __foo: number; }'. Did you mean to write '__foo'? + + +==== tests/cases/compiler/spellingSuggestionLeadingUnderscores01.ts (2 errors) ==== + // @filename abc.ts + export declare let a: { + __foo: 10, + } + + a.___foo + ~~~~~~ +!!! error TS2551: Property '___foo' does not exist on type '{ __foo: 10; }'. Did you mean '__foo'? + + // @filename def.ts + export let b: { + __foo: number + } + + b = { + ___foo: 100, + ~~~~~~~~~~~ +!!! error TS2322: Type '{ ___foo: number; }' is not assignable to type '{ __foo: number; }'. +!!! error TS2322: Object literal may only specify known properties, but '___foo' does not exist in type '{ __foo: number; }'. Did you mean to write '__foo'? + } + + \ No newline at end of file diff --git a/tests/baselines/reference/spellingSuggestionLeadingUnderscores01.js b/tests/baselines/reference/spellingSuggestionLeadingUnderscores01.js new file mode 100644 index 00000000000..6a84749b153 --- /dev/null +++ b/tests/baselines/reference/spellingSuggestionLeadingUnderscores01.js @@ -0,0 +1,26 @@ +//// [spellingSuggestionLeadingUnderscores01.ts] +// @filename abc.ts +export declare let a: { + __foo: 10, +} + +a.___foo + +// @filename def.ts +export let b: { + __foo: number +} + +b = { + ___foo: 100, +} + + + +//// [spellingSuggestionLeadingUnderscores01.js] +"use strict"; +exports.__esModule = true; +exports.a.___foo; +exports.b = { + ___foo: 100 +}; diff --git a/tests/cases/compiler/spellingSuggestionLeadingUnderscores01.ts b/tests/cases/compiler/spellingSuggestionLeadingUnderscores01.ts new file mode 100644 index 00000000000..cf60136f5eb --- /dev/null +++ b/tests/cases/compiler/spellingSuggestionLeadingUnderscores01.ts @@ -0,0 +1,17 @@ +// @module: commonjs +// @filename abc.ts +export declare let a: { + __foo: 10, +} + +a.___foo + +// @filename def.ts +export let b: { + __foo: number +} + +b = { + ___foo: 100, +} +