Skip to content

Commit

Permalink
Allow extraction of type from type assertions for declaration emit
Browse files Browse the repository at this point in the history
  • Loading branch information
dragomirtitian committed Mar 1, 2024
1 parent 297ba1b commit 9399b32
Show file tree
Hide file tree
Showing 19 changed files with 499 additions and 179 deletions.
265 changes: 214 additions & 51 deletions src/compiler/transformers/declarations.ts

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src/compiler/transformers/declarations/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
DiagnosticMessage,
Diagnostics,
ElementAccessExpression,
ExportAssignment,
ExpressionWithTypeArguments,
FunctionDeclaration,
GetAccessorDeclaration,
Expand All @@ -24,6 +25,7 @@ import {
isConstructorDeclaration,
isConstructSignatureDeclaration,
isElementAccessExpression,
isExportAssignment,
isExpressionWithTypeArguments,
isFunctionDeclaration,
isGetAccessor,
Expand Down Expand Up @@ -100,7 +102,8 @@ export type DeclarationDiagnosticProducing =
| BinaryExpression
| JSDocTypedefTag
| JSDocCallbackTag
| JSDocEnumTag;
| JSDocEnumTag
| ExportAssignment;

/** @internal */
export function canProduceDiagnostics(node: Node): node is DeclarationDiagnosticProducing {
Expand Down Expand Up @@ -231,9 +234,18 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD
else if (isTypeAliasDeclaration(node) || isJSDocTypeAlias(node)) {
return getTypeAliasDeclarationVisibilityError;
}
else if (isExportAssignment(node)) {
return getExportAssignmentTypeVisibilityDiagnosticMessage;
}
else {
return Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${Debug.formatSyntaxKind((node as Node).kind)}`);
}
function getExportAssignmentTypeVisibilityDiagnosticMessage() {
return {
diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
errorNode: node,
};
}

function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) {
if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
accessorDeclarationEmitVisibilityErrors.ts(2,18): error TS2304: Cannot find name 'DoesNotExist'.
accessorDeclarationEmitVisibilityErrors.ts(2,18): error TS4106: Parameter 'arg' of accessor has or is using private name 'DoesNotExist'.


==== accessorDeclarationEmitVisibilityErrors.ts (2 errors) ====
==== accessorDeclarationEmitVisibilityErrors.ts (1 errors) ====
export class Q {
set bet(arg: DoesNotExist) {}
~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'DoesNotExist'.
~~~~~~~~~~~~
!!! error TS4106: Parameter 'arg' of accessor has or is using private name 'DoesNotExist'.
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ export class Q {
export class Q {
set bet(arg) { }
}


//// [accessorDeclarationEmitVisibilityErrors.d.ts]
export declare class Q {
set bet(arg: DoesNotExist);
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/coAndContraVariantInferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ interface Action<TName extends string, TPayload> {
name: TName;
payload: TPayload;
}
declare const actionA: Action<"ACTION_A", string>;
declare const actionB: Action<"ACTION_B", boolean>;
declare const actionA: Action<'ACTION_A', string>;
declare const actionB: Action<'ACTION_B', boolean>;
declare function call<TName extends string, TPayload>(action: Action<TName, TPayload>, fn: (action: Action<TName, TPayload>) => any): void;
declare const printFn: (action: typeof actionA | typeof actionB) => void;
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ var x = {};
//// [duplicatePropertiesInTypeAssertions02.d.ts]
declare let x: {
a: number;
a: number;
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ hugeDeclarationOutputGetsTruncatedWithError.ts(5,14): error TS7056: The inferred

type manyprops = `${props}${props}`;

export const c = null as any as {[K in manyprops]: {[K2 in manyprops]: `${K}.${K2}`}};
export const c = () => null as any as {[K in manyprops]: {[K2 in manyprops]: `${K}.${K2}`}};
~
!!! error TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ type props = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "

type manyprops = `${props}${props}`;

export const c = null as any as {[K in manyprops]: {[K2 in manyprops]: `${K}.${K2}`}};
export const c = () => null as any as {[K in manyprops]: {[K2 in manyprops]: `${K}.${K2}`}};

//// [hugeDeclarationOutputGetsTruncatedWithError.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.c = void 0;
exports.c = null;
var c = function () { return null; };
exports.c = c;
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ type manyprops = `${props}${props}`;
>props : Symbol(props, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 0, 0))
>props : Symbol(props, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 0, 0))

export const c = null as any as {[K in manyprops]: {[K2 in manyprops]: `${K}.${K2}`}};
export const c = () => null as any as {[K in manyprops]: {[K2 in manyprops]: `${K}.${K2}`}};
>c : Symbol(c, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 12))
>K : Symbol(K, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 34))
>K : Symbol(K, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 40))
>manyprops : Symbol(manyprops, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 0, 167))
>K2 : Symbol(K2, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 53))
>K2 : Symbol(K2, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 59))
>manyprops : Symbol(manyprops, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 0, 167))
>K : Symbol(K, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 34))
>K2 : Symbol(K2, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 53))
>K : Symbol(K, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 40))
>K2 : Symbol(K2, Decl(hugeDeclarationOutputGetsTruncatedWithError.ts, 4, 59))

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/baselines/reference/namedTupleMembers.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export declare const func: Func<SegmentAnnotated>;
export declare function useState<T>(initial: T): [value: T, setter: (T: any) => void];
export type Iter = Func<[step: number, iterations: number]>;
export declare function readSegment([length, count]: [number, number]): void;
export declare const val: [number, number];
export declare const val: Parameters<typeof readSegment>[0];
export type RecursiveTupleA = [initial: string, next: RecursiveTupleA];
export type RecursiveTupleB = [first: string, ptr: RecursiveTupleB];
export type RecusiveRest = [first: string, ...rest: RecusiveRest[]];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const vLiteral = null! as "1" | "1"
type R = { foo: string }

export class C {
// under !strictNullChecks all types can be reused from the assertion
// under strictNullChecks we need to add undefined, and we can't always know we can
// Can't know if references contain undefined, fall back to inference
tsResolve? = null! as R | R;
tsResolve2? = null! as R | R | string;
Expand Down Expand Up @@ -148,6 +150,8 @@ exports.vStringLiteral = null;
exports.vLiteral = null;
var C = /** @class */ (function () {
function C() {
// under !strictNullChecks all types can be reused from the assertion
// under strictNullChecks we need to add undefined, and we can't always know we can
// Can't know if references contain undefined, fall back to inference
this.tsResolve = null;
this.tsResolve2 = null;
Expand All @@ -168,75 +172,56 @@ exports.C = C;


//// [assertToTypeReferences.d.ts]
export declare let vLet: {
type P = {} & {
name: string;
};
export declare const vConst: {
name: string;
};
export declare function fn(p?: {
name: string;
}): void;
export declare function fnWithRequiredDefaultParam(p: {
name: string;
}, req: number): void;
export declare let vLet: P;
export declare const vConst: P;
export declare function fn(p?: P): void;
export declare function fnWithRequiredDefaultParam(p: P, req: number): void;
export declare class C {
ctorField: {
name: string;
};
field: {
name: string;
};
readonly roFiled: {
name: string;
};
method(p?: {
name: string;
}): void;
methodWithRequiredDefault(p: {
name: string;
}, req: number): void;
methodWithRequiredDefault2(p: {
name: string;
}, req: number): void;
constructor(ctorField?: {
name: string;
});
ctorField: P;
field: P;
readonly roFiled: P;
method(p?: P): void;
methodWithRequiredDefault(p: P, req: number): void;
methodWithRequiredDefault2(p: P, req: number): void;
constructor(ctorField?: P);
}
declare const _default: {
name: string;
};
export default _default;
//// [assertToTypeLiteral.d.ts]
export declare let vLet: {
export declare let vLet: {} & {
name: string;
};
export declare const vConst: {
export declare const vConst: {} & {
name: string;
};
export declare function fn(p?: {
export declare function fn(p?: {} & {
name: string;
}): void;
export declare function fnWithRequiredDefaultParam(p: {
export declare function fnWithRequiredDefaultParam(p: {} & {
name: string;
}, req: number): void;
export declare class C {
ctorField: {
ctorField: {} & {
name: string;
};
field: {
field: {} & {
name: string;
};
readonly roFiled: {
readonly roFiled: {} & {
name: string;
};
method(p?: {
method(p?: {} & {
name: string;
}): void;
methodWithRequiredDefault(p: {
methodWithRequiredDefault(p: {} & {
name: string;
}, req: number): void;
constructor(ctorField?: {
constructor(ctorField?: {} & {
name: string;
});
get x(): {
Expand All @@ -251,23 +236,23 @@ declare const _default: {
};
export default _default;
//// [assertToOtherTypes.d.ts]
export declare const vNumberLiteral: 1;
export declare const vStringLiteral: "1";
export declare const vLiteral: "1";
export declare const vNumberLiteral: 1 | 1;
export declare const vStringLiteral: "1" | "1";
export declare const vLiteral: "1" | "1";
type R = {
foo: string;
};
export declare class C {
tsResolve?: R;
tsResolve2?: string | R;
reuseType?: string | ((p: R) => void);
reuseType2?: string | (new (p: R) => R);
reuseType3?: any;
reuseType4?: [R, R, R];
reuseType5?: R[];
reuseType6?: 1 | "2" | 1n;
reuseType7?: "A";
reuseType8?: `${string}-ok`;
reuseType9?: this;
tsResolve?: R | R;
tsResolve2?: R | R | string;
reuseType?: ((p: R) => void) | string | string;
reuseType2?: (new (p: R) => R) | string | string;
reuseType3?: string | number | bigint | symbol | unknown | any | never | symbol;
reuseType4?: [R, R, R] | [R, R, R];
reuseType5?: R[] | R[];
reuseType6?: 1 | "2" | 1n | 1n;
reuseType7?: `A` | `A`;
reuseType8?: `${string}-ok` | `${string}-ok`;
reuseType9?: this | this;
}
export {};
Original file line number Diff line number Diff line change
Expand Up @@ -136,34 +136,36 @@ type R = { foo: string }
export class C {
>C : Symbol(C, Decl(assertToOtherTypes.ts, 4, 24))

// under !strictNullChecks all types can be reused from the assertion
// under strictNullChecks we need to add undefined, and we can't always know we can
// Can't know if references contain undefined, fall back to inference
tsResolve? = null! as R | R;
>tsResolve : Symbol(C.tsResolve, Decl(assertToOtherTypes.ts, 6, 16))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))

tsResolve2? = null! as R | R | string;
>tsResolve2 : Symbol(C.tsResolve2, Decl(assertToOtherTypes.ts, 8, 32))
>tsResolve2 : Symbol(C.tsResolve2, Decl(assertToOtherTypes.ts, 10, 32))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))

// Simple type. we can add undefined
reuseType? = null! as ((p: R) => void) | string | string;
>reuseType : Symbol(C.reuseType, Decl(assertToOtherTypes.ts, 9, 42))
>p : Symbol(p, Decl(assertToOtherTypes.ts, 11, 28))
>reuseType : Symbol(C.reuseType, Decl(assertToOtherTypes.ts, 11, 42))
>p : Symbol(p, Decl(assertToOtherTypes.ts, 13, 28))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))

reuseType2? = null! as (new (p: R) => R) | string | string;
>reuseType2 : Symbol(C.reuseType2, Decl(assertToOtherTypes.ts, 11, 61))
>p : Symbol(p, Decl(assertToOtherTypes.ts, 12, 33))
>reuseType2 : Symbol(C.reuseType2, Decl(assertToOtherTypes.ts, 13, 61))
>p : Symbol(p, Decl(assertToOtherTypes.ts, 14, 33))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))

reuseType3? = null! as string | number | bigint | symbol | unknown | any | never | symbol;
>reuseType3 : Symbol(C.reuseType3, Decl(assertToOtherTypes.ts, 12, 63))
>reuseType3 : Symbol(C.reuseType3, Decl(assertToOtherTypes.ts, 14, 63))

reuseType4? = null! as [R, R, R] | [R, R, R];
>reuseType4 : Symbol(C.reuseType4, Decl(assertToOtherTypes.ts, 13, 94))
>reuseType4 : Symbol(C.reuseType4, Decl(assertToOtherTypes.ts, 15, 94))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))
Expand All @@ -172,19 +174,19 @@ export class C {
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))

reuseType5? = null! as R[] | R[];
>reuseType5 : Symbol(C.reuseType5, Decl(assertToOtherTypes.ts, 14, 49))
>reuseType5 : Symbol(C.reuseType5, Decl(assertToOtherTypes.ts, 16, 49))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))
>R : Symbol(R, Decl(assertToOtherTypes.ts, 2, 42))

reuseType6? = null! as 1 | "2" | 1n | 1n;
>reuseType6 : Symbol(C.reuseType6, Decl(assertToOtherTypes.ts, 15, 37))
>reuseType6 : Symbol(C.reuseType6, Decl(assertToOtherTypes.ts, 17, 37))

reuseType7? = null! as `A` | `A`;
>reuseType7 : Symbol(C.reuseType7, Decl(assertToOtherTypes.ts, 16, 45))
>reuseType7 : Symbol(C.reuseType7, Decl(assertToOtherTypes.ts, 18, 45))

reuseType8? = null! as `${string}-ok` | `${string}-ok`;
>reuseType8 : Symbol(C.reuseType8, Decl(assertToOtherTypes.ts, 17, 37))
>reuseType8 : Symbol(C.reuseType8, Decl(assertToOtherTypes.ts, 19, 37))

reuseType9? = null! as this | this;
>reuseType9 : Symbol(C.reuseType9, Decl(assertToOtherTypes.ts, 18, 59))
>reuseType9 : Symbol(C.reuseType9, Decl(assertToOtherTypes.ts, 20, 59))
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ type R = { foo: string }
export class C {
>C : C

// under !strictNullChecks all types can be reused from the assertion
// under strictNullChecks we need to add undefined, and we can't always know we can
// Can't know if references contain undefined, fall back to inference
tsResolve? = null! as R | R;
>tsResolve : R
Expand Down
Loading

0 comments on commit 9399b32

Please sign in to comment.