Skip to content

Commit 6a0ea87

Browse files
author
Max Heiber
committed
begin update checker for private names
- [x] treat private names as unique: - case 1: cannot say that a variable is of a class type unless the variable points to an instance of the class - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts) - case 2: private names in class hierarchies do not conflict - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts) - [x] `#constructor` is reserved - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts) - check in `bindWorker`, where every node is visited - [x] Accessibility modifiers can't be used with private names - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts) - implemented in `checkAccessibilityModifiers`, using `ModifierFlags.AccessibilityModifier` - [x] `delete #foo` not allowed - [x] Private name accesses not allowed outside of the defining class - see test: https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts) - implemented in `checkDeleteExpression` - [x] Do [the right thing](https://gist.github.com/mheiber/b6fc7adb426c2e1cdaceb5d7786fc630) for nested classes Signed-off-by: Max Heiber <mheiber@bloomberg.net>
1 parent 548c9f8 commit 6a0ea87

File tree

73 files changed

+1495
-36
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1495
-36
lines changed

src/compiler/binder.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,10 @@ namespace ts {
266266
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
267267
return getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>nameExpression).name));
268268
}
269-
if (isPrivateName(node)) {
270-
return nodePosToString(node) as __String;
269+
if (isPrivateName(name)) {
270+
// containingClass exists because private names only allowed inside classes
271+
const containingClassSymbol = getContainingClass(name.parent)!.symbol;
272+
return getPropertyNameForPrivateNameDescription(containingClassSymbol, name.escapedText);
271273
}
272274
return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined;
273275
}
@@ -325,6 +327,10 @@ namespace ts {
325327

326328
const isDefaultExport = hasModifier(node, ModifierFlags.Default);
327329

330+
// need this before getDeclarationName
331+
if (isNamedDeclaration(node)) {
332+
node.name.parent = node;
333+
}
328334
// The exported symbol for an export default function/class node is always named "default"
329335
const name = isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node);
330336

@@ -377,10 +383,6 @@ namespace ts {
377383
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
378384
}
379385
else {
380-
if (isNamedDeclaration(node)) {
381-
node.name.parent = node;
382-
}
383-
384386
// Report errors every position with duplicate declaration
385387
// Report errors on previous encountered declarations
386388
let message = symbol.flags & SymbolFlags.BlockScopedVariable
@@ -1798,6 +1800,18 @@ namespace ts {
17981800
return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode;
17991801
}
18001802

1803+
// The binder visits every node, so this is a good place to check for
1804+
// the reserved private name (there is only one)
1805+
function checkPrivateName(node: PrivateName) {
1806+
if (node.escapedText === "#constructor") {
1807+
// Report error only if there are no parse errors in file
1808+
if (!file.parseDiagnostics.length) {
1809+
file.bindDiagnostics.push(createDiagnosticForNode(node,
1810+
Diagnostics.constructor_is_a_reserved_word, declarationNameToString(node)));
1811+
}
1812+
}
1813+
}
1814+
18011815
function checkStrictModeBinaryExpression(node: BinaryExpression) {
18021816
if (inStrictMode && isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) {
18031817
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
@@ -2070,6 +2084,8 @@ namespace ts {
20702084
node.flowNode = currentFlow;
20712085
}
20722086
return checkStrictModeIdentifier(<Identifier>node);
2087+
case SyntaxKind.PrivateName:
2088+
return checkPrivateName(node as PrivateName);
20732089
case SyntaxKind.PropertyAccessExpression:
20742090
case SyntaxKind.ElementAccessExpression:
20752091
if (currentFlow && isNarrowableReference(<Expression>node)) {

src/compiler/checker.ts

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,8 +1523,8 @@ namespace ts {
15231523
}
15241524
}
15251525

1526-
function diagnosticName(nameArg: __String | Identifier) {
1527-
return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier);
1526+
function diagnosticName(nameArg: __String | Identifier | PrivateName) {
1527+
return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier | PrivateName);
15281528
}
15291529

15301530
function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) {
@@ -2594,15 +2594,16 @@ namespace ts {
25942594
return getUnionType(arrayFrom(typeofEQFacts.keys(), getLiteralType));
25952595
}
25962596

2597-
// A reserved member name starts with two underscores, but the third character cannot be an underscore
2598-
// or the @ symbol. A third underscore indicates an escaped form of an identifer that started
2597+
// A reserved member name starts with two underscores, but the third character cannot be an underscore,
2598+
// @ or #. A third underscore indicates an escaped form of an identifer that started
25992599
// with at least two underscores. The @ character indicates that the name is denoted by a well known ES
2600-
// Symbol instance.
2600+
// Symbol instance and the # indicates that the name is a PrivateName.
26012601
function isReservedMemberName(name: __String) {
26022602
return (name as string).charCodeAt(0) === CharacterCodes._ &&
26032603
(name as string).charCodeAt(1) === CharacterCodes._ &&
26042604
(name as string).charCodeAt(2) !== CharacterCodes._ &&
2605-
(name as string).charCodeAt(2) !== CharacterCodes.at;
2605+
(name as string).charCodeAt(2) !== CharacterCodes.at &&
2606+
(name as string).charCodeAt(2) !== CharacterCodes.hash;
26062607
}
26072608

26082609
function getNamedMembers(members: SymbolTable): Symbol[] {
@@ -9042,7 +9043,9 @@ namespace ts {
90429043
}
90439044

90449045
function getLiteralTypeFromPropertyName(prop: Symbol, include: TypeFlags) {
9045-
if (!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) {
9046+
const hasNonPublicModifier = !!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier);
9047+
const hasPrivateName = prop.valueDeclaration && isNamedDeclaration(prop.valueDeclaration) && isPrivateName(prop.valueDeclaration.name);
9048+
if (!hasNonPublicModifier && !hasPrivateName) {
90469049
let type = getLateBoundSymbol(prop).nameType;
90479050
if (!type && !isKnownSymbol(prop)) {
90489051
const name = prop.valueDeclaration && getNameOfDeclaration(prop.valueDeclaration);
@@ -17974,6 +17977,46 @@ namespace ts {
1797417977
return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
1797517978
}
1797617979

17980+
function getPropertyByPrivateName(apparentType: Type, leftType: Type, right: PrivateName): Symbol | undefined {
17981+
let classWithShadowedPrivateName;
17982+
let klass = getContainingClass(right);
17983+
while (klass) {
17984+
const symbolTableKey = getPropertyNameForPrivateNameDescription(klass.symbol, right.escapedText);
17985+
if (symbolTableKey) {
17986+
const prop = getPropertyOfType(apparentType, symbolTableKey);
17987+
if (prop) {
17988+
if (classWithShadowedPrivateName) {
17989+
error(
17990+
right,
17991+
Diagnostics.This_usage_of_0_refers_to_the_private_member_declared_in_its_enclosing_class_While_type_1_has_a_private_member_of_the_same_name_its_declaration_and_accessibility_is_distinct,
17992+
diagnosticName(right),
17993+
diagnosticName(classWithShadowedPrivateName.name || ("anonymous" as __String))
17994+
);
17995+
return undefined;
17996+
}
17997+
return prop;
17998+
}
17999+
else {
18000+
classWithShadowedPrivateName = klass;
18001+
}
18002+
}
18003+
klass = getContainingClass(klass);
18004+
}
18005+
// If this isn't a case of shadowing, and the lhs has a property with the same
18006+
// private name description, then there is a privacy violation
18007+
if (leftType.symbol.members) {
18008+
const symbolTableKey = getPropertyNameForPrivateNameDescription(leftType.symbol, right.escapedText);
18009+
if (symbolTableKey) {
18010+
const prop = getPropertyOfType(apparentType, symbolTableKey);
18011+
if (prop) {
18012+
error(right, Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_name, symbolToString(prop), typeToString(getDeclaringClass(prop)!));
18013+
}
18014+
}
18015+
}
18016+
// not found
18017+
return undefined;
18018+
}
18019+
1797718020
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier | PrivateName) {
1797818021
let propType: Type;
1797918022
const leftType = checkNonNullExpression(left);
@@ -17986,7 +18029,7 @@ namespace ts {
1798618029
return apparentType;
1798718030
}
1798818031
const assignmentKind = getAssignmentTargetKind(node);
17989-
const prop = getPropertyOfType(apparentType, right.escapedText);
18032+
const prop = isPrivateName(right) ? getPropertyByPrivateName(apparentType, leftType, right) : getPropertyOfType(apparentType, right.escapedText);
1799018033
if (isIdentifier(left) && parentSymbol && !(prop && isConstEnumOrConstEnumOnlyModule(prop))) {
1799118034
markAliasReferenced(parentSymbol, node);
1799218035
}
@@ -20725,10 +20768,16 @@ namespace ts {
2072520768
error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference);
2072620769
return booleanType;
2072720770
}
20771+
if (expr.kind === SyntaxKind.PropertyAccessExpression && isPrivateName((expr as PropertyAccessExpression).name)) {
20772+
error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_name);
20773+
20774+
}
2072820775
const links = getNodeLinks(expr);
2072920776
const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol);
20730-
if (symbol && isReadonlySymbol(symbol)) {
20731-
error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
20777+
if (symbol) {
20778+
if (isReadonlySymbol(symbol)) {
20779+
error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
20780+
}
2073220781
}
2073320782
return booleanType;
2073420783
}
@@ -21878,9 +21927,6 @@ namespace ts {
2187821927
checkGrammarDecoratorsAndModifiers(node);
2187921928

2188021929
checkVariableLikeDeclaration(node);
21881-
if (node.name && isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) {
21882-
error(node, Diagnostics.Private_names_cannot_be_used_as_parameters);
21883-
}
2188421930
const func = getContainingFunction(node)!;
2188521931
if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) {
2188621932
if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
@@ -28515,6 +28561,9 @@ namespace ts {
2851528561
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (<ParameterDeclaration>node).dotDotDotToken) {
2851628562
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter);
2851728563
}
28564+
else if (isNamedDeclaration(node) && (flags & ModifierFlags.AccessibilityModifier) && node.name.kind === SyntaxKind.PrivateName) {
28565+
return grammarErrorOnNode(node, Diagnostics.Accessibility_modifiers_cannot_be_used_with_private_names);
28566+
}
2851828567
if (flags & ModifierFlags.Async) {
2851928568
return checkGrammarAsyncModifier(node, lastAsync!);
2852028569
}
@@ -29293,10 +29342,6 @@ namespace ts {
2929329342
checkESModuleMarker(node.name);
2929429343
}
2929529344

29296-
if (isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) {
29297-
return grammarErrorOnNode(node.name, Diagnostics.Private_names_are_not_allowed_in_variable_declarations);
29298-
}
29299-
2930029345
const checkLetConstNames = (isLet(node) || isVarConst(node));
2930129346

2930229347
// 1. LexicalDeclaration : LetOrConst BindingList ;

src/compiler/diagnosticMessages.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4166,14 +4166,26 @@
41664166
"category": "Error",
41674167
"code": 18003
41684168
},
4169-
"Private names are not allowed in variable declarations.": {
4169+
"Accessibility modifiers cannot be used with private names.": {
41704170
"category": "Error",
41714171
"code": 18004
41724172
},
4173-
"Private names cannot be used as parameters": {
4173+
"The operand of a delete operator cannot be a private name.": {
41744174
"category": "Error",
41754175
"code": 18005
41764176
},
4177+
"#constructor is a reserved word.": {
4178+
"category": "Error",
4179+
"code": 18006
4180+
},
4181+
"Property '{0}' is not accessible outside class '{1}' because it has a private name.": {
4182+
"category": "Error",
4183+
"code": 18007
4184+
},
4185+
"This usage of '{0}' refers to the private member declared in its enclosing class. While type '{1}' has a private member of the same name, its declaration and accessibility is distinct.": {
4186+
"category": "Error",
4187+
"code": 18008
4188+
},
41774189

41784190
"File is a CommonJS module; it may be converted to an ES6 module.": {
41794191
"category": "Suggestion",

src/compiler/utilities.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2672,6 +2672,10 @@ namespace ts {
26722672
return "__@" + symbolName as __String;
26732673
}
26742674

2675+
export function getPropertyNameForPrivateNameDescription(containingClassSymbol: Symbol, description: __String): __String {
2676+
return `__#${getSymbolId(containingClassSymbol)}@${description}` as __String;
2677+
}
2678+
26752679
export function isKnownSymbol(symbol: Symbol): boolean {
26762680
return startsWith(symbol.escapedName as string, "__@");
26772681
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
EmitSkipped: false
2+
FileName : ./dist/index.js
3+
"use strict";
4+
Object.defineProperty(exports, "__esModule", { value: true });
5+
var Foo = /** @class */ (function () {
6+
function Foo() {
7+
}
8+
Foo.prototype.methodName = function (propName) { };
9+
Foo.prototype.otherMethod = function () {
10+
if (Math.random() > 0.5) {
11+
return { x: 42 };
12+
}
13+
return { y: "yes" };
14+
};
15+
return Foo;
16+
}());
17+
exports.Foo = Foo;
18+
FileName : ./dist/index.d.ts.map
19+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
20+
export declare class Foo {
21+
member: string;
22+
methodName(propName: SomeType): void;
23+
otherMethod(): {
24+
x: number;
25+
y?: undefined;
26+
} | {
27+
y: string;
28+
x?: undefined;
29+
};
30+
}
31+
export interface SomeType {
32+
member: number;
33+
}
34+
//# sourceMappingURL=index.d.ts.map
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
EmitSkipped: false
2+
FileName : ./dist/index.js.map
3+
{"version":3,"file":"index.js","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":";;AAAA;IAAA;IASA,CAAC;IAPG,wBAAU,GAAV,UAAW,QAAkB,IAAS,CAAC;IACvC,yBAAW,GAAX;QACI,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE;YACrB,OAAO,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC;SAClB;QACD,OAAO,EAAC,CAAC,EAAE,KAAK,EAAC,CAAC;IACtB,CAAC;IACL,UAAC;AAAD,CAAC,AATD,IASC;AATY,kBAAG"}FileName : ./dist/index.js
4+
"use strict";
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
var Foo = /** @class */ (function () {
7+
function Foo() {
8+
}
9+
Foo.prototype.methodName = function (propName) { };
10+
Foo.prototype.otherMethod = function () {
11+
if (Math.random() > 0.5) {
12+
return { x: 42 };
13+
}
14+
return { y: "yes" };
15+
};
16+
return Foo;
17+
}());
18+
exports.Foo = Foo;
19+
//# sourceMappingURL=index.js.mapFileName : ./dist/index.d.ts.map
20+
{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
21+
export declare class Foo {
22+
member: string;
23+
methodName(propName: SomeType): void;
24+
otherMethod(): {
25+
x: number;
26+
y?: undefined;
27+
} | {
28+
y: string;
29+
x?: undefined;
30+
};
31+
}
32+
export interface SomeType {
33+
member: number;
34+
}
35+
//# sourceMappingURL=index.d.ts.map
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
EmitSkipped: false
2+
FileName : ./dist/index.js
3+
"use strict";
4+
Object.defineProperty(exports, "__esModule", { value: true });
5+
var Foo = /** @class */ (function () {
6+
function Foo() {
7+
}
8+
Foo.prototype.methodName = function (propName) { };
9+
Foo.prototype.otherMethod = function () {
10+
if (Math.random() > 0.5) {
11+
return { x: 42 };
12+
}
13+
return { y: "yes" };
14+
};
15+
return Foo;
16+
}());
17+
exports.Foo = Foo;
18+
FileName : ./dist/index.d.ts.map
19+
{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
20+
export declare class Foo {
21+
member: string;
22+
methodName(propName: SomeType): void;
23+
otherMethod(): {
24+
x: number;
25+
y?: undefined;
26+
} | {
27+
y: string;
28+
x?: undefined;
29+
};
30+
}
31+
export interface SomeType {
32+
member: number;
33+
}
34+
//# sourceMappingURL=index.d.ts.map
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
EmitSkipped: false
2+
FileName : ./dist/index.js
3+
"use strict";
4+
Object.defineProperty(exports, "__esModule", { value: true });
5+
var Foo = /** @class */ (function () {
6+
function Foo() {
7+
}
8+
Foo.prototype.methodName = function (propName) { };
9+
Foo.prototype.otherMethod = function () {
10+
if (Math.random() > 0.5) {
11+
return { x: 42 };
12+
}
13+
return { y: "yes" };
14+
};
15+
return Foo;
16+
}());
17+
exports.Foo = Foo;
18+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0cy9jYXNlcy9mb3Vyc2xhc2gvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTtJQUFBO0lBU0EsQ0FBQztJQVBHLHdCQUFVLEdBQVYsVUFBVyxRQUFrQixJQUFTLENBQUM7SUFDdkMseUJBQVcsR0FBWDtRQUNJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRTtZQUNyQixPQUFPLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBQyxDQUFDO1NBQ2xCO1FBQ0QsT0FBTyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0wsVUFBQztBQUFELENBQUMsQUFURCxJQVNDO0FBVFksa0JBQUcifQ==FileName : ./dist/index.d.ts.map
19+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
20+
export declare class Foo {
21+
member: string;
22+
methodName(propName: SomeType): void;
23+
otherMethod(): {
24+
x: number;
25+
y?: undefined;
26+
} | {
27+
y: string;
28+
x?: undefined;
29+
};
30+
}
31+
export interface SomeType {
32+
member: number;
33+
}
34+
//# sourceMappingURL=index.d.ts.map

0 commit comments

Comments
 (0)