diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 03d0f166b81..265099bd6e7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -7749,17 +7749,17 @@ namespace ts { context.pragmas = createMap() as PragmaMap; for (const pragma of pragmas) { - if (context.pragmas.has(pragma!.name)) { // TODO: GH#18217 - const currentValue = context.pragmas.get(pragma!.name); + if (context.pragmas.has(pragma.name)) { + const currentValue = context.pragmas.get(pragma.name); if (currentValue instanceof Array) { - currentValue.push(pragma!.args); + currentValue.push(pragma.args); } else { - context.pragmas.set(pragma!.name, [currentValue, pragma!.args]); + context.pragmas.set(pragma.name, [currentValue, pragma.args]); } continue; } - context.pragmas.set(pragma!.name, pragma!.args); + context.pragmas.set(pragma.name, pragma.args); } } @@ -7783,9 +7783,8 @@ namespace ts { const typeReferenceDirectives = context.typeReferenceDirectives; const libReferenceDirectives = context.libReferenceDirectives; forEach(toArray(entryOrList), (arg: PragmaPseudoMap["reference"]) => { - // TODO: GH#18217 - const { types, lib, path } = arg!.arguments; - if (arg!.arguments["no-default-lib"]) { + const { types, lib, path } = arg.arguments; + if (arg.arguments["no-default-lib"]) { context.hasNoDefaultLib = true; } else if (types) { @@ -7798,7 +7797,7 @@ namespace ts { referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value }); } else { - reportDiagnostic(arg!.range.pos, arg!.range.end - arg!.range.pos, Diagnostics.Invalid_reference_directive_syntax); + reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax); } }); break; @@ -7806,7 +7805,7 @@ namespace ts { case "amd-dependency": { context.amdDependencies = map( toArray(entryOrList), - (x: PragmaPseudoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217 + (x: PragmaPseudoMap["amd-dependency"]) => ({ name: x.arguments.name, path: x.arguments.path })); break; } case "amd-module": { @@ -7814,13 +7813,13 @@ namespace ts { for (const entry of entryOrList) { if (context.moduleName) { // TODO: It's probably fine to issue this diagnostic on all instances of the pragma - reportDiagnostic(entry!.range.pos, entry!.range.end - entry!.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); + reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); } - context.moduleName = (entry as PragmaPseudoMap["amd-module"])!.arguments.name; + context.moduleName = (entry as PragmaPseudoMap["amd-module"]).arguments.name; } } else { - context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"])!.arguments.name; + context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"]).arguments.name; } break; } @@ -7828,11 +7827,11 @@ namespace ts { case "ts-check": { // _last_ of either nocheck or check in a file is the "winner" forEach(toArray(entryOrList), entry => { - if (!context.checkJsDirective || entry!.range.pos > context.checkJsDirective.pos) { // TODO: GH#18217 + if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) { context.checkJsDirective = { enabled: key === "ts-check", - end: entry!.range.end, - pos: entry!.range.pos + end: entry.range.end, + pos: entry.range.pos }; } }); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bcc3218a017..55492081050 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5950,26 +5950,18 @@ namespace ts { /* @internal */ export interface PragmaDefinition { args?: - | [PragmaArgumentSpecification] - | [PragmaArgumentSpecification, PragmaArgumentSpecification] - | [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification] - | [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification]; + | readonly [PragmaArgumentSpecification] + | readonly [PragmaArgumentSpecification, PragmaArgumentSpecification] + | readonly [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification] + | readonly [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification]; // If not present, defaults to PragmaKindFlags.Default kind?: PragmaKindFlags; } - /** - * This function only exists to cause exact types to be inferred for all the literals within `commentPragmas` - */ - /* @internal */ - function _contextuallyTypePragmas}, K1 extends string, K2 extends string, K3 extends string, K4 extends string>(args: T): T { - return args; - } - // While not strictly a type, this is here because `PragmaMap` needs to be here to be used with `SourceFile`, and we don't // fancy effectively defining it twice, once in value-space and once in type-space /* @internal */ - export const commentPragmas = _contextuallyTypePragmas({ + export const commentPragmas = { "reference": { args: [ { name: "types", optional: true, captureSpan: true }, @@ -5997,7 +5989,7 @@ namespace ts { args: [{ name: "factory" }], kind: PragmaKindFlags.MultiLine }, - }); + } as const; /* @internal */ type PragmaArgTypeMaybeCapture = TDesc extends {captureSpan: true} ? {value: string, pos: number, end: number} : string; @@ -6008,29 +6000,29 @@ namespace ts { ? {[K in TName]?: PragmaArgTypeMaybeCapture} : {[K in TName]: PragmaArgTypeMaybeCapture}; + /* @internal */ + type UnionToIntersection = + (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; + + /* @internal */ + type ArgumentDefinitionToFieldUnion[]> = { + [K in keyof T]: PragmaArgTypeOptional + }[Extract]; // The mapped type maps over only the tuple members, but this reindex gets _all_ members - by extracting only `number` keys, we get only the tuple members + /** * Maps a pragma definition into the desired shape for its arguments object - * Maybe the below is a good argument for types being iterable on struture in some way. */ /* @internal */ - type PragmaArgumentType = - T extends { args: [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification] } - ? PragmaArgTypeOptional & PragmaArgTypeOptional & PragmaArgTypeOptional & PragmaArgTypeOptional - : T extends { args: [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification] } - ? PragmaArgTypeOptional & PragmaArgTypeOptional & PragmaArgTypeOptional - : T extends { args: [PragmaArgumentSpecification, PragmaArgumentSpecification] } - ? PragmaArgTypeOptional & PragmaArgTypeOptional - : T extends { args: [PragmaArgumentSpecification] } - ? PragmaArgTypeOptional - : object; - // The above fallback to `object` when there's no args to allow `{}` (as intended), but not the number 2, for example - // TODO: Swap to `undefined` for a cleaner API once strictNullChecks is enabled + type PragmaArgumentType = + ConcretePragmaSpecs[KPrag] extends { args: readonly PragmaArgumentSpecification[] } + ? UnionToIntersection> + : never; /* @internal */ type ConcretePragmaSpecs = typeof commentPragmas; /* @internal */ - export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType, range: CommentRange}}; + export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]: {arguments: PragmaArgumentType, range: CommentRange}}; /* @internal */ export type PragmaPseudoMapEntry = {[K in keyof PragmaPseudoMap]: {name: K, args: PragmaPseudoMap[K]}}[keyof PragmaPseudoMap];