Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
13 changes: 12 additions & 1 deletion src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ import {
tryCast,
TypeAliasDeclaration,
TypeNode,
TypeOperatorNode,
TypeParameterDeclaration,
TypeReferenceNode,
unescapeLeadingUnderscores,
Expand Down Expand Up @@ -1479,7 +1480,10 @@ export function transformDeclarations(context: TransformationContext): Transform
exportMappings.push([name, nameStr]);
}
const varDecl = factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, /*initializer*/ undefined);
return factory.createVariableStatement(isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([varDecl]));
const modifiers = isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)];
const isConst = isUniqueSymbolType(type);
const variableDeclarationList = factory.createVariableDeclarationList([varDecl], isConst ? NodeFlags.Const : NodeFlags.None);
return factory.createVariableStatement(modifiers, variableDeclarationList);
});
if (!exportMappings.length) {
declarations = mapDefined(declarations, declaration => factory.replaceModifiers(declaration, ModifierFlags.None));
Expand Down Expand Up @@ -1817,6 +1821,13 @@ export function transformDeclarations(context: TransformationContext): Transform
return isExportAssignment(node) || isExportDeclaration(node);
}

function isUniqueSymbolType(type: TypeNode | undefined): boolean {
return !!type &&
type.kind === SyntaxKind.TypeOperator &&
(type as TypeOperatorNode).operator === SyntaxKind.UniqueKeyword &&
(type as TypeOperatorNode).type.kind === SyntaxKind.SymbolKeyword;
}

function hasScopeMarker(statements: readonly Statement[]) {
return some(statements, isScopeMarker);
}
Expand Down
38 changes: 38 additions & 0 deletions tests/baselines/reference/uniqueSymbolReassignment.d.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//// [tests/cases/compiler/uniqueSymbolReassignment.d.ts] ////

=== uniqueSymbolReassignment.d.ts ===
declare function myFunction(): void;
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.d.ts, 0, 0), Decl(uniqueSymbolReassignment.d.ts, 0, 36))

declare namespace myFunction {
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.d.ts, 0, 0), Decl(uniqueSymbolReassignment.d.ts, 0, 36))

const mySymbol: unique symbol;
>mySymbol : Symbol(mySymbol, Decl(uniqueSymbolReassignment.d.ts, 2, 9))

const anotherUnique: unique symbol;
>anotherUnique : Symbol(anotherUnique, Decl(uniqueSymbolReassignment.d.ts, 3, 9))

var nonUnique1: typeof nonUniqueSymbol1;
>nonUnique1 : Symbol(nonUnique1, Decl(uniqueSymbolReassignment.d.ts, 4, 7))
>nonUniqueSymbol1 : Symbol(nonUniqueSymbol1, Decl(uniqueSymbolReassignment.d.ts, 9, 13))

var nonUnique2: typeof nonUniqueSymbol2;
>nonUnique2 : Symbol(nonUnique2, Decl(uniqueSymbolReassignment.d.ts, 5, 7))
>nonUniqueSymbol2 : Symbol(nonUniqueSymbol2, Decl(uniqueSymbolReassignment.d.ts, 10, 13))

var normalVar: string;
>normalVar : Symbol(normalVar, Decl(uniqueSymbolReassignment.d.ts, 6, 7))

var symbolName: string;
>symbolName : Symbol(symbolName, Decl(uniqueSymbolReassignment.d.ts, 7, 7))
}
declare const nonUniqueSymbol1: unique symbol;
>nonUniqueSymbol1 : Symbol(nonUniqueSymbol1, Decl(uniqueSymbolReassignment.d.ts, 9, 13))

declare const nonUniqueSymbol2: unique symbol;
>nonUniqueSymbol2 : Symbol(nonUniqueSymbol2, Decl(uniqueSymbolReassignment.d.ts, 10, 13))

export { myFunction };
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.d.ts, 11, 8))

51 changes: 51 additions & 0 deletions tests/baselines/reference/uniqueSymbolReassignment.d.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//// [tests/cases/compiler/uniqueSymbolReassignment.d.ts] ////

=== uniqueSymbolReassignment.d.ts ===
declare function myFunction(): void;
>myFunction : typeof myFunction
> : ^^^^^^^^^^^^^^^^^

declare namespace myFunction {
>myFunction : typeof myFunction
> : ^^^^^^^^^^^^^^^^^

const mySymbol: unique symbol;
>mySymbol : unique symbol
> : ^^^^^^^^^^^^^

const anotherUnique: unique symbol;
>anotherUnique : unique symbol
> : ^^^^^^^^^^^^^

var nonUnique1: typeof nonUniqueSymbol1;
>nonUnique1 : unique symbol
> : ^^^^^^^^^^^^^
>nonUniqueSymbol1 : unique symbol
> : ^^^^^^^^^^^^^

var nonUnique2: typeof nonUniqueSymbol2;
>nonUnique2 : unique symbol
> : ^^^^^^^^^^^^^
>nonUniqueSymbol2 : unique symbol
> : ^^^^^^^^^^^^^

var normalVar: string;
>normalVar : string
> : ^^^^^^

var symbolName: string;
>symbolName : string
> : ^^^^^^
}
declare const nonUniqueSymbol1: unique symbol;
>nonUniqueSymbol1 : unique symbol
> : ^^^^^^^^^^^^^

declare const nonUniqueSymbol2: unique symbol;
>nonUniqueSymbol2 : unique symbol
> : ^^^^^^^^^^^^^

export { myFunction };
>myFunction : typeof myFunction
> : ^^^^^^^^^^^^^^^^^

48 changes: 48 additions & 0 deletions tests/baselines/reference/uniqueSymbolReassignment.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
uniqueSymbolReassignment.ts(2,18): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.
uniqueSymbolReassignment.ts(7,23): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.
uniqueSymbolReassignment.ts(19,26): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.
uniqueSymbolReassignment.ts(20,26): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.


==== uniqueSymbolReassignment.ts (4 errors) ====
// This is a unique symbol (const + Symbol())
const mySymbol = Symbol('Symbols.mySymbol');
~~~~~~
!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.
const Symbols = {
mySymbol
} as const;

const anotherUnique = Symbol('symbols.anotherUnique');
~~~~~~
!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.
const Symbols2 = {
anotherUnique
} as const;

function myFunction() {}

// Attach the unique ones
myFunction.mySymbol = Symbols.mySymbol;
myFunction.anotherUnique = Symbols2.anotherUnique;

// Non-unique symbols (regular Symbol() without const)
const nonUniqueSymbol1 = Symbol('nonUnique1');
~~~~~~
!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.
const nonUniqueSymbol2 = Symbol('nonUnique2');
~~~~~~
!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.

// Plain text variables (not symbols at all)
const normalVar = "not a symbol";
const symbolName = "this contains symbol but is not one";

// Attach those as well
myFunction.nonUnique1 = nonUniqueSymbol1;
myFunction.nonUnique2 = nonUniqueSymbol2;
myFunction.normalVar = normalVar;
myFunction.symbolName = symbolName;

export { myFunction };

78 changes: 78 additions & 0 deletions tests/baselines/reference/uniqueSymbolReassignment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//// [tests/cases/compiler/uniqueSymbolReassignment.ts] ////

//// [uniqueSymbolReassignment.ts]
// This is a unique symbol (const + Symbol())
const mySymbol = Symbol('Symbols.mySymbol');
const Symbols = {
mySymbol
} as const;

const anotherUnique = Symbol('symbols.anotherUnique');
const Symbols2 = {
anotherUnique
} as const;

function myFunction() {}

// Attach the unique ones
myFunction.mySymbol = Symbols.mySymbol;
myFunction.anotherUnique = Symbols2.anotherUnique;

// Non-unique symbols (regular Symbol() without const)
const nonUniqueSymbol1 = Symbol('nonUnique1');
const nonUniqueSymbol2 = Symbol('nonUnique2');

// Plain text variables (not symbols at all)
const normalVar = "not a symbol";
const symbolName = "this contains symbol but is not one";

// Attach those as well
myFunction.nonUnique1 = nonUniqueSymbol1;
myFunction.nonUnique2 = nonUniqueSymbol2;
myFunction.normalVar = normalVar;
myFunction.symbolName = symbolName;

export { myFunction };


//// [uniqueSymbolReassignment.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.myFunction = myFunction;
// This is a unique symbol (const + Symbol())
var mySymbol = Symbol('Symbols.mySymbol');
var Symbols = {
mySymbol: mySymbol
};
var anotherUnique = Symbol('symbols.anotherUnique');
var Symbols2 = {
anotherUnique: anotherUnique
};
function myFunction() { }
// Attach the unique ones
myFunction.mySymbol = Symbols.mySymbol;
myFunction.anotherUnique = Symbols2.anotherUnique;
// Non-unique symbols (regular Symbol() without const)
var nonUniqueSymbol1 = Symbol('nonUnique1');
var nonUniqueSymbol2 = Symbol('nonUnique2');
// Plain text variables (not symbols at all)
var normalVar = "not a symbol";
var symbolName = "this contains symbol but is not one";
// Attach those as well
myFunction.nonUnique1 = nonUniqueSymbol1;
myFunction.nonUnique2 = nonUniqueSymbol2;
myFunction.normalVar = normalVar;
myFunction.symbolName = symbolName;


//// [uniqueSymbolReassignment.d.ts]
declare function myFunction(): void;
declare namespace myFunction {
var mySymbol: any;
var anotherUnique: any;
var nonUnique1: any;
var nonUnique2: any;
var normalVar: string;
var symbolName: string;
}
export { myFunction };
90 changes: 90 additions & 0 deletions tests/baselines/reference/uniqueSymbolReassignment.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//// [tests/cases/compiler/uniqueSymbolReassignment.ts] ////

=== uniqueSymbolReassignment.ts ===
// This is a unique symbol (const + Symbol())
const mySymbol = Symbol('Symbols.mySymbol');
>mySymbol : Symbol(mySymbol, Decl(uniqueSymbolReassignment.ts, 1, 5))

const Symbols = {
>Symbols : Symbol(Symbols, Decl(uniqueSymbolReassignment.ts, 2, 5))

mySymbol
>mySymbol : Symbol(mySymbol, Decl(uniqueSymbolReassignment.ts, 2, 17))

} as const;
>const : Symbol(const)

const anotherUnique = Symbol('symbols.anotherUnique');
>anotherUnique : Symbol(anotherUnique, Decl(uniqueSymbolReassignment.ts, 6, 5))

const Symbols2 = {
>Symbols2 : Symbol(Symbols2, Decl(uniqueSymbolReassignment.ts, 7, 5))

anotherUnique
>anotherUnique : Symbol(anotherUnique, Decl(uniqueSymbolReassignment.ts, 7, 18))

} as const;
>const : Symbol(const)

function myFunction() {}
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 9, 11), Decl(uniqueSymbolReassignment.ts, 11, 24), Decl(uniqueSymbolReassignment.ts, 14, 39), Decl(uniqueSymbolReassignment.ts, 23, 57), Decl(uniqueSymbolReassignment.ts, 26, 41) ... and 2 more)

// Attach the unique ones
myFunction.mySymbol = Symbols.mySymbol;
>myFunction.mySymbol : Symbol(myFunction.mySymbol, Decl(uniqueSymbolReassignment.ts, 11, 24))
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 9, 11), Decl(uniqueSymbolReassignment.ts, 11, 24), Decl(uniqueSymbolReassignment.ts, 14, 39), Decl(uniqueSymbolReassignment.ts, 23, 57), Decl(uniqueSymbolReassignment.ts, 26, 41) ... and 2 more)
>mySymbol : Symbol(myFunction.mySymbol, Decl(uniqueSymbolReassignment.ts, 11, 24))
>Symbols.mySymbol : Symbol(mySymbol, Decl(uniqueSymbolReassignment.ts, 2, 17))
>Symbols : Symbol(Symbols, Decl(uniqueSymbolReassignment.ts, 2, 5))
>mySymbol : Symbol(mySymbol, Decl(uniqueSymbolReassignment.ts, 2, 17))

myFunction.anotherUnique = Symbols2.anotherUnique;
>myFunction.anotherUnique : Symbol(myFunction.anotherUnique, Decl(uniqueSymbolReassignment.ts, 14, 39))
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 9, 11), Decl(uniqueSymbolReassignment.ts, 11, 24), Decl(uniqueSymbolReassignment.ts, 14, 39), Decl(uniqueSymbolReassignment.ts, 23, 57), Decl(uniqueSymbolReassignment.ts, 26, 41) ... and 2 more)
>anotherUnique : Symbol(myFunction.anotherUnique, Decl(uniqueSymbolReassignment.ts, 14, 39))
>Symbols2.anotherUnique : Symbol(anotherUnique, Decl(uniqueSymbolReassignment.ts, 7, 18))
>Symbols2 : Symbol(Symbols2, Decl(uniqueSymbolReassignment.ts, 7, 5))
>anotherUnique : Symbol(anotherUnique, Decl(uniqueSymbolReassignment.ts, 7, 18))

// Non-unique symbols (regular Symbol() without const)
const nonUniqueSymbol1 = Symbol('nonUnique1');
>nonUniqueSymbol1 : Symbol(nonUniqueSymbol1, Decl(uniqueSymbolReassignment.ts, 18, 5))

const nonUniqueSymbol2 = Symbol('nonUnique2');
>nonUniqueSymbol2 : Symbol(nonUniqueSymbol2, Decl(uniqueSymbolReassignment.ts, 19, 5))

// Plain text variables (not symbols at all)
const normalVar = "not a symbol";
>normalVar : Symbol(normalVar, Decl(uniqueSymbolReassignment.ts, 22, 5))

const symbolName = "this contains symbol but is not one";
>symbolName : Symbol(symbolName, Decl(uniqueSymbolReassignment.ts, 23, 5))

// Attach those as well
myFunction.nonUnique1 = nonUniqueSymbol1;
>myFunction.nonUnique1 : Symbol(myFunction.nonUnique1, Decl(uniqueSymbolReassignment.ts, 23, 57))
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 9, 11), Decl(uniqueSymbolReassignment.ts, 11, 24), Decl(uniqueSymbolReassignment.ts, 14, 39), Decl(uniqueSymbolReassignment.ts, 23, 57), Decl(uniqueSymbolReassignment.ts, 26, 41) ... and 2 more)
>nonUnique1 : Symbol(myFunction.nonUnique1, Decl(uniqueSymbolReassignment.ts, 23, 57))
>nonUniqueSymbol1 : Symbol(nonUniqueSymbol1, Decl(uniqueSymbolReassignment.ts, 18, 5))

myFunction.nonUnique2 = nonUniqueSymbol2;
>myFunction.nonUnique2 : Symbol(myFunction.nonUnique2, Decl(uniqueSymbolReassignment.ts, 26, 41))
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 9, 11), Decl(uniqueSymbolReassignment.ts, 11, 24), Decl(uniqueSymbolReassignment.ts, 14, 39), Decl(uniqueSymbolReassignment.ts, 23, 57), Decl(uniqueSymbolReassignment.ts, 26, 41) ... and 2 more)
>nonUnique2 : Symbol(myFunction.nonUnique2, Decl(uniqueSymbolReassignment.ts, 26, 41))
>nonUniqueSymbol2 : Symbol(nonUniqueSymbol2, Decl(uniqueSymbolReassignment.ts, 19, 5))

myFunction.normalVar = normalVar;
>myFunction.normalVar : Symbol(myFunction.normalVar, Decl(uniqueSymbolReassignment.ts, 27, 41))
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 9, 11), Decl(uniqueSymbolReassignment.ts, 11, 24), Decl(uniqueSymbolReassignment.ts, 14, 39), Decl(uniqueSymbolReassignment.ts, 23, 57), Decl(uniqueSymbolReassignment.ts, 26, 41) ... and 2 more)
>normalVar : Symbol(myFunction.normalVar, Decl(uniqueSymbolReassignment.ts, 27, 41))
>normalVar : Symbol(normalVar, Decl(uniqueSymbolReassignment.ts, 22, 5))

myFunction.symbolName = symbolName;
>myFunction.symbolName : Symbol(myFunction.symbolName, Decl(uniqueSymbolReassignment.ts, 28, 33))
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 9, 11), Decl(uniqueSymbolReassignment.ts, 11, 24), Decl(uniqueSymbolReassignment.ts, 14, 39), Decl(uniqueSymbolReassignment.ts, 23, 57), Decl(uniqueSymbolReassignment.ts, 26, 41) ... and 2 more)
>symbolName : Symbol(myFunction.symbolName, Decl(uniqueSymbolReassignment.ts, 28, 33))
>symbolName : Symbol(symbolName, Decl(uniqueSymbolReassignment.ts, 23, 5))

export { myFunction };
>myFunction : Symbol(myFunction, Decl(uniqueSymbolReassignment.ts, 31, 8))

Loading
Loading