Use const contexts and tuple mapped types to simplify some explicitly elucidated types (#30654)

* Use const contexts and tuple mapped types to simplify some explicitly elucidated types

* Fix lint

* Further cleanup - refactor mapped type into its own alias for readability

* Slightly more cleanup - PragmaPsuedoMap neednt be partial, thus removing tons of nonull assertions

* Remove GH#18217 comments
This commit is contained in:
Wesley Wigham
2019-04-02 13:04:51 -07:00
committed by GitHub
parent bf0dd79e4a
commit ca98a50574
2 changed files with 35 additions and 44 deletions
+15 -16
View File
@@ -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
};
}
});
+20 -28
View File
@@ -5950,26 +5950,18 @@ namespace ts {
/* @internal */
export interface PragmaDefinition<T1 extends string = string, T2 extends string = string, T3 extends string = string, T4 extends string = string> {
args?:
| [PragmaArgumentSpecification<T1>]
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>]
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>]
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>, PragmaArgumentSpecification<T4>];
| readonly [PragmaArgumentSpecification<T1>]
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>]
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>]
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>, PragmaArgumentSpecification<T4>];
// 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<T extends {[name: string]: PragmaDefinition<K1, K2, K3, K4>}, 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> = TDesc extends {captureSpan: true} ? {value: string, pos: number, end: number} : string;
@@ -6008,29 +6000,29 @@ namespace ts {
? {[K in TName]?: PragmaArgTypeMaybeCapture<TDesc>}
: {[K in TName]: PragmaArgTypeMaybeCapture<TDesc>};
/* @internal */
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
/* @internal */
type ArgumentDefinitionToFieldUnion<T extends readonly PragmaArgumentSpecification<any>[]> = {
[K in keyof T]: PragmaArgTypeOptional<T[K], T[K] extends {name: infer TName} ? TName extends string ? TName : never : never>
}[Extract<keyof T, number>]; // 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 PragmaDefinition> =
T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>, PragmaArgumentSpecification<infer TName3>, PragmaArgumentSpecification<infer TName4>] }
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2> & PragmaArgTypeOptional<T["args"][2], TName3> & PragmaArgTypeOptional<T["args"][2], TName4>
: T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>, PragmaArgumentSpecification<infer TName3>] }
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2> & PragmaArgTypeOptional<T["args"][2], TName3>
: T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>] }
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2>
: T extends { args: [PragmaArgumentSpecification<infer TName>] }
? PragmaArgTypeOptional<T["args"][0], TName>
: 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<KPrag extends keyof ConcretePragmaSpecs> =
ConcretePragmaSpecs[KPrag] extends { args: readonly PragmaArgumentSpecification<any>[] }
? UnionToIntersection<ArgumentDefinitionToFieldUnion<ConcretePragmaSpecs[KPrag]["args"]>>
: never;
/* @internal */
type ConcretePragmaSpecs = typeof commentPragmas;
/* @internal */
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]: {arguments: PragmaArgumentType<K>, range: CommentRange}};
/* @internal */
export type PragmaPseudoMapEntry = {[K in keyof PragmaPseudoMap]: {name: K, args: PragmaPseudoMap[K]}}[keyof PragmaPseudoMap];