Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44674,8 +44674,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return location ? evaluateEnumMember(expr, symbol, location) : getEnumMemberValue(symbol.valueDeclaration as EnumMember);
}
if (isConstantVariable(symbol)) {
const declaration = symbol.valueDeclaration as VariableDeclaration | undefined;
if (declaration && !declaration.type && declaration.initializer && (!location || declaration !== location && isBlockScopedNameDeclaredBeforeUse(declaration, location))) {
const declaration = symbol.valueDeclaration;
if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && (!location || declaration !== location && isBlockScopedNameDeclaredBeforeUse(declaration, location))) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternatively, I could check if the parent is not a BindingElement

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that break on parameters? I guess not, since isConstantVariable won't be true.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll also note that this feels weird because declaration is VariableDeclaration which must have kind === SyntaxKind.VariableDeclaration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll also note that this feels weird because declaration is VariableDeclaration which must have kind === SyntaxKind.VariableDeclaration.

Good catch! I didn't notice it. It is VariableDeclaration just because of the cast - so I'll make that cast more accurate in a second :)

return evaluate(declaration.initializer, declaration);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
enumErrorOnConstantBindingWithInitializer.ts(9,10): error TS18033: Type 'string | number' is not assignable to type 'number' as required for computed enum member values.
Type 'string' is not assignable to type 'number'.


==== enumErrorOnConstantBindingWithInitializer.ts (1 errors) ====
type Thing = {
value?: string | number;
};

declare const thing: Thing;
const { value = "123" } = thing;

enum E {
test = value,
~~~~~
!!! error TS18033: Type 'string | number' is not assignable to type 'number' as required for computed enum member values.
!!! error TS18033: Type 'string' is not assignable to type 'number'.
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/enums/enumErrorOnConstantBindingWithInitializer.ts] ////

//// [enumErrorOnConstantBindingWithInitializer.ts]
type Thing = {
value?: string | number;
};

declare const thing: Thing;
const { value = "123" } = thing;

enum E {
test = value,
}


//// [enumErrorOnConstantBindingWithInitializer.js]
"use strict";
var _a = thing.value, value = _a === void 0 ? "123" : _a;
var E;
(function (E) {
E[E["test"] = value] = "test";
})(E || (E = {}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//// [tests/cases/conformance/enums/enumErrorOnConstantBindingWithInitializer.ts] ////

=== enumErrorOnConstantBindingWithInitializer.ts ===
type Thing = {
>Thing : Symbol(Thing, Decl(enumErrorOnConstantBindingWithInitializer.ts, 0, 0))

value?: string | number;
>value : Symbol(value, Decl(enumErrorOnConstantBindingWithInitializer.ts, 0, 14))

};

declare const thing: Thing;
>thing : Symbol(thing, Decl(enumErrorOnConstantBindingWithInitializer.ts, 4, 13))
>Thing : Symbol(Thing, Decl(enumErrorOnConstantBindingWithInitializer.ts, 0, 0))

const { value = "123" } = thing;
>value : Symbol(value, Decl(enumErrorOnConstantBindingWithInitializer.ts, 5, 7))
>thing : Symbol(thing, Decl(enumErrorOnConstantBindingWithInitializer.ts, 4, 13))

enum E {
>E : Symbol(E, Decl(enumErrorOnConstantBindingWithInitializer.ts, 5, 32))

test = value,
>test : Symbol(E.test, Decl(enumErrorOnConstantBindingWithInitializer.ts, 7, 8))
>value : Symbol(value, Decl(enumErrorOnConstantBindingWithInitializer.ts, 5, 7))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//// [tests/cases/conformance/enums/enumErrorOnConstantBindingWithInitializer.ts] ////

=== enumErrorOnConstantBindingWithInitializer.ts ===
type Thing = {
>Thing : { value?: string | number | undefined; }

value?: string | number;
>value : string | number | undefined

};

declare const thing: Thing;
>thing : Thing

const { value = "123" } = thing;
>value : string | number
>"123" : "123"
>thing : Thing

enum E {
>E : E

test = value,
>test : E.test
>value : string | number
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//// [tests/cases/compiler/templateExpressionNoInlininingOfConstantBindingWithInitializer.ts] ////

//// [templateExpressionNoInlininingOfConstantBindingWithInitializer.ts]
type Params = {
value?: string | number
}

function example(parameters: Params) {
const { value = '123' } = parameters
return `${value}` === '345'
}

function example2(parameters: Params) {
const { value = '123' } = parameters
const b = `${value}`;
return b;
}


//// [templateExpressionNoInlininingOfConstantBindingWithInitializer.js]
function example(parameters) {
var _a = parameters.value, value = _a === void 0 ? '123' : _a;
return "".concat(value) === '345';
}
function example2(parameters) {
var _a = parameters.value, value = _a === void 0 ? '123' : _a;
var b = "".concat(value);
return b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//// [tests/cases/compiler/templateExpressionNoInlininingOfConstantBindingWithInitializer.ts] ////

=== templateExpressionNoInlininingOfConstantBindingWithInitializer.ts ===
type Params = {
>Params : Symbol(Params, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 0, 0))

value?: string | number
>value : Symbol(value, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 0, 15))
}

function example(parameters: Params) {
>example : Symbol(example, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 2, 1))
>parameters : Symbol(parameters, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 4, 17))
>Params : Symbol(Params, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 0, 0))

const { value = '123' } = parameters
>value : Symbol(value, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 5, 9))
>parameters : Symbol(parameters, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 4, 17))

return `${value}` === '345'
>value : Symbol(value, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 5, 9))
}

function example2(parameters: Params) {
>example2 : Symbol(example2, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 7, 1))
>parameters : Symbol(parameters, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 9, 18))
>Params : Symbol(Params, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 0, 0))

const { value = '123' } = parameters
>value : Symbol(value, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 10, 9))
>parameters : Symbol(parameters, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 9, 18))

const b = `${value}`;
>b : Symbol(b, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 11, 7))
>value : Symbol(value, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 10, 9))

return b;
>b : Symbol(b, Decl(templateExpressionNoInlininingOfConstantBindingWithInitializer.ts, 11, 7))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//// [tests/cases/compiler/templateExpressionNoInlininingOfConstantBindingWithInitializer.ts] ////

=== templateExpressionNoInlininingOfConstantBindingWithInitializer.ts ===
type Params = {
>Params : { value?: string | number; }

value?: string | number
>value : string | number
}

function example(parameters: Params) {
>example : (parameters: Params) => boolean
>parameters : Params

const { value = '123' } = parameters
>value : string | number
>'123' : "123"
>parameters : Params

return `${value}` === '345'
>`${value}` === '345' : boolean
>`${value}` : string
>value : string | number
>'345' : "345"
}

function example2(parameters: Params) {
>example2 : (parameters: Params) => string
>parameters : Params

const { value = '123' } = parameters
>value : string | number
>'123' : "123"
>parameters : Params

const b = `${value}`;
>b : string
>`${value}` : string
>value : string | number

return b;
>b : string
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Params = {
value?: string | number
}

function example(parameters: Params) {
const { value = '123' } = parameters
return `${value}` === '345'
}

function example2(parameters: Params) {
const { value = '123' } = parameters
const b = `${value}`;
return b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// @strict: true

type Thing = {
value?: string | number;
};

declare const thing: Thing;
const { value = "123" } = thing;

enum E {
test = value,
}