From 9d298a13a1edee38a6d9a30fab153cfca6ac44f6 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Mon, 20 Nov 2017 16:43:02 -0800 Subject: [PATCH 01/32] [WIP] enable updating ATA files --- src/compiler/types.ts | 10 --- src/harness/unittests/typingsInstaller.ts | 6 +- src/server/types.ts | 1 + .../typingsInstaller/nodeTypingsInstaller.ts | 2 +- .../typingsInstaller/typingsInstaller.ts | 86 +++++++++++++++++-- src/services/jsTyping.ts | 21 +++-- src/services/shims.ts | 10 +++ .../reference/api/tsserverlibrary.d.ts | 9 -- tests/baselines/reference/api/typescript.d.ts | 9 -- 9 files changed, 112 insertions(+), 42 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 23798635671..673db399d0d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3999,16 +3999,6 @@ namespace ts { [option: string]: string[] | boolean | undefined; } - export interface DiscoverTypingsInfo { - fileNames: string[]; // The file names that belong to the same project. - projectRootPath: string; // The path to the project root directory - safeListPath: string; // The path used to retrieve the safe list - packageNameToTypingLocation: Map; // The map of package names to their cached typing locations - typeAcquisition: TypeAcquisition; // Used to customize the type acquisition process - compilerOptions: CompilerOptions; // Used as a source for typing inference - unresolvedImports: ReadonlyArray; // List of unresolved module ids from imports - } - export enum ModuleKind { None = 0, CommonJS = 1, diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index a84520095a4..5c2f8758916 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1148,7 +1148,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f]); - const cache = createMap(); + const cache = createMap(); for (const name of JsTyping.nodeCoreModuleList) { const logger = trackingLogger(); @@ -1171,7 +1171,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f, node]); - const cache = createMapFromTemplate({ node: node.path }); + const cache = createMapFromTemplate({ node: { typingLocation: node.path, timestamp: Date.now() } }); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"]); assert.deepEqual(logger.finish(), [ @@ -1196,7 +1196,7 @@ namespace ts.projectSystem { content: JSON.stringify({ name: "b" }), }; const host = createServerHost([app, a, b]); - const cache = createMap(); + const cache = createMap(); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, /*unresolvedImports*/ []); assert.deepEqual(logger.finish(), [ diff --git a/src/server/types.ts b/src/server/types.ts index 32132ed278b..69b1dae0d7c 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -128,5 +128,6 @@ declare namespace ts.server { writeFile(path: string, content: string): void; createDirectory(path: string): void; watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; + getModifiedTime?(path: string): Date; } } \ No newline at end of file diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 36f5adab400..378708a4a81 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -185,7 +185,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`); } - const command = `${this.npmPath} install --ignore-scripts ${packageNames.join(" ")} --save-dev --user-agent="typesInstaller/${version}"`; + const command = `${this.npmPath} install@latest --ignore-scripts ${packageNames.join(" ")} --save-dev --force --user-agent="typesInstaller/${version}"`; const start = Date.now(); const hasError = this.execSyncAndLog(command, { cwd }); if (this.log.isEnabled()) { diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 283770d1dc8..fe629b353b7 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -41,13 +41,74 @@ namespace ts.server.typingsInstaller { onRequestCompleted: RequestCompletedAction; } + interface TypeDeclarationTimestampFile { + entries: MapLike; + } + + function loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, host: InstallTypingHost, log: Log): Map { + const fileExists = host.fileExists(typeDeclarationTimestampFilePath); + if (!fileExists) { + if (log.isEnabled()) { + log.writeLine(`Type declaration timestamp file '${typeDeclarationTimestampFilePath}' does not exist`); + } + } + try { + if (fileExists) { + const content = JSON.parse(host.readFile(typeDeclarationTimestampFilePath)); + return createMapFromTemplate(content.entries); + } + else { + host.writeFile(typeDeclarationTimestampFilePath, "{}"); + if (log.isEnabled()) { + log.writeLine("Type declaration timestamp file was created."); + } + return createMap(); + } + } + catch (e) { + if (log.isEnabled()) { + log.writeLine(`Error when loading type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); + } + return createMap(); + } + } + + function writeTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, newContents: TypeDeclarationTimestampFile, host: InstallTypingHost, log: Log): void { + const fileExists = host.fileExists(typeDeclarationTimestampFilePath); + if (!fileExists) { + if (log.isEnabled()) { + log.writeLine(`Type declaration timestamp file '${typeDeclarationTimestampFilePath}' does not exist`); + } + } + try { + if (fileExists) { + host.writeFile(typeDeclarationTimestampFilePath, JSON.stringify(newContents)); + return; + } + else { + host.writeFile(typeDeclarationTimestampFilePath, JSON.stringify(newContents)); + if (log.isEnabled()) { + log.writeLine("Type declaration time stamp file was created."); + } + return; + } + } + catch (e) { + if (log.isEnabled()) { + log.writeLine(`Error when writing new type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); + } + return; + } + } + export abstract class TypingsInstaller { - private readonly packageNameToTypingLocation: Map = createMap(); + private readonly packageNameToTypingLocation: Map = createMap(); private readonly missingTypingsSet: Map = createMap(); private readonly knownCachesSet: Map = createMap(); private readonly projectWatchers: Map = createMap(); private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; + private typeDeclarationTimestamps: Map = createMap(); private installRunCount = 1; private inFlightRequestCount = 0; @@ -162,6 +223,8 @@ namespace ts.server.typingsInstaller { } return; } + const timestampJson = combinePaths(cacheLocation, "timestamps.json"); + this.typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampJson, this.installTypingHost, this.log); const packageJson = combinePaths(cacheLocation, "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Trying to find '${packageJson}'...`); @@ -184,7 +247,7 @@ namespace ts.server.typingsInstaller { continue; } const existingTypingFile = this.packageNameToTypingLocation.get(packageName); - if (existingTypingFile === typingFile) { + if (existingTypingFile.typingLocation === typingFile) { continue; } if (existingTypingFile) { @@ -195,7 +258,15 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Adding entry into typings cache: '${packageName}' => '${typingFile}'`); } - this.packageNameToTypingLocation.set(packageName, typingFile); + if (this.typeDeclarationTimestamps.get(key) === undefined) { + // getModifiedTime is only undefined if we were to use the ChakraHost, but we never do in this scenario + // defaults to old behavior of never updating if we ever use a host without getModifiedTime in the future + const timestamp = this.installTypingHost.getModifiedTime === undefined ? Date.now() : this.installTypingHost.getModifiedTime(typingFile).getTime(); + this.typeDeclarationTimestamps.set(key, timestamp); + } + // timestamp guaranteed to not be undefined by above check + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: this.typeDeclarationTimestamps.get(key) }; + this.packageNameToTypingLocation.set(packageName, newTyping); } } } @@ -211,7 +282,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) this.log.writeLine(`'${typing}' is in missingTypingsSet - skipping...`); return false; } - if (this.packageNameToTypingLocation.get(typing)) { + if (this.packageNameToTypingLocation.get(typing) && !JsTyping.isTypingExpired(this.packageNameToTypingLocation.get(typing))) { if (this.log.isEnabled()) this.log.writeLine(`'${typing}' already has a typing - skipping...`); return false; } @@ -295,7 +366,9 @@ namespace ts.server.typingsInstaller { continue; } if (!this.packageNameToTypingLocation.has(packageName)) { - this.packageNameToTypingLocation.set(packageName, typingFile); + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: Date.now() }; + this.packageNameToTypingLocation.set(packageName, newTyping); + this.typeDeclarationTimestamps.set(packageName, Date.now()); } installedTypingFiles.push(typingFile); } @@ -303,6 +376,9 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Installed typing files ${JSON.stringify(installedTypingFiles)}`); } + const newFileContents: TypeDeclarationTimestampFile = { entries: this.typeDeclarationTimestamps }; + writeTypeDeclarationTimestampFile(cachePath, newFileContents, this.installTypingHost, this.log); // WRONG PATH + this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); } finally { diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 1c2f87fa428..85660a03368 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -26,6 +26,17 @@ namespace ts.JsTyping { typings?: string; } + export interface CachedTyping { + typingLocation: string; + timestamp: number; + } + + const typingLifetime = new Date(0, 1); + + export function isTypingExpired(typing: JsTyping.CachedTyping | undefined) { + return typing && Date.now() - typingLifetime.getTime() < typing.timestamp; + } + /* @internal */ export const nodeCoreModuleList: ReadonlyArray = [ "buffer", "querystring", "events", "http", "cluster", @@ -60,7 +71,7 @@ namespace ts.JsTyping { * @param fileNames are the file names that belong to the same project * @param projectRootPath is the path to the project root directory * @param safeListPath is the path used to retrieve the safe list - * @param packageNameToTypingLocation is the map of package names to their cached typing locations + * @param packageNameToTypingLocation is the map of package names to their cached typing locations and time of caching * @param typeAcquisition is used to customize the typing acquisition process * @param compilerOptions are used as a source for typing inference */ @@ -70,7 +81,7 @@ namespace ts.JsTyping { fileNames: string[], projectRootPath: Path, safeList: SafeList, - packageNameToTypingLocation: ReadonlyMap, + packageNameToTypingLocation: ReadonlyMap, typeAcquisition: TypeAcquisition, unresolvedImports: ReadonlyArray): { cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } { @@ -122,9 +133,9 @@ namespace ts.JsTyping { addInferredTypings(module, "Inferred typings from unresolved imports"); } // Add the cached typing locations for inferred typings that are already installed - packageNameToTypingLocation.forEach((typingLocation, name) => { - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined) { - inferredTypings.set(name, typingLocation); + packageNameToTypingLocation.forEach((typing, name) => { + if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && !isTypingExpired(typing)) { + inferredTypings.set(name, typing.typingLocation); } }); diff --git a/src/services/shims.ts b/src/services/shims.ts index fda698785b3..d4bad1908e9 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -24,6 +24,16 @@ let debugObjectHost: { CollectGarbage(): void } = (function (this: any) { return /* @internal */ namespace ts { + interface DiscoverTypingsInfo { + fileNames: string[]; // The file names that belong to the same project. + projectRootPath: string; // The path to the project root directory + safeListPath: string; // The path used to retrieve the safe list + packageNameToTypingLocation: Map; // The map of package names to their cached typing locations + typeAcquisition: TypeAcquisition; // Used to customize the type acquisition process + compilerOptions: CompilerOptions; // Used as a source for typing inference + unresolvedImports: ReadonlyArray; // List of unresolved module ids from imports + } + export interface ScriptSnapshotShim { /** Gets a portion of the script snapshot specified by [start, end). */ getText(start: number, end: number): string; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3eabea4435a..d5a5c7a1a72 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2308,15 +2308,6 @@ declare namespace ts { exclude?: string[]; [option: string]: string[] | boolean | undefined; } - interface DiscoverTypingsInfo { - fileNames: string[]; - projectRootPath: string; - safeListPath: string; - packageNameToTypingLocation: Map; - typeAcquisition: TypeAcquisition; - compilerOptions: CompilerOptions; - unresolvedImports: ReadonlyArray; - } enum ModuleKind { None = 0, CommonJS = 1, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 630b7a08a28..fef3baf9e36 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2308,15 +2308,6 @@ declare namespace ts { exclude?: string[]; [option: string]: string[] | boolean | undefined; } - interface DiscoverTypingsInfo { - fileNames: string[]; - projectRootPath: string; - safeListPath: string; - packageNameToTypingLocation: Map; - typeAcquisition: TypeAcquisition; - compilerOptions: CompilerOptions; - unresolvedImports: ReadonlyArray; - } enum ModuleKind { None = 0, CommonJS = 1, From ee5e8e3eee90bb975c3a952abb560472527df61e Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 27 Nov 2017 23:29:10 -0500 Subject: [PATCH 02/32] Ensure proper JSON writing behavior of timestamps --- .../typingsInstaller/typingsInstaller.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index fe629b353b7..a3b96a4e02e 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -45,7 +45,7 @@ namespace ts.server.typingsInstaller { entries: MapLike; } - function loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, host: InstallTypingHost, log: Log): Map { + function loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, host: InstallTypingHost, log: Log): MapLike { const fileExists = host.fileExists(typeDeclarationTimestampFilePath); if (!fileExists) { if (log.isEnabled()) { @@ -55,21 +55,21 @@ namespace ts.server.typingsInstaller { try { if (fileExists) { const content = JSON.parse(host.readFile(typeDeclarationTimestampFilePath)); - return createMapFromTemplate(content.entries); + return content.entries; } else { host.writeFile(typeDeclarationTimestampFilePath, "{}"); if (log.isEnabled()) { log.writeLine("Type declaration timestamp file was created."); } - return createMap(); + return {}; } } catch (e) { if (log.isEnabled()) { log.writeLine(`Error when loading type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); } - return createMap(); + return {}; } } @@ -108,7 +108,7 @@ namespace ts.server.typingsInstaller { private readonly projectWatchers: Map = createMap(); private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; - private typeDeclarationTimestamps: Map = createMap(); + private typeDeclarationTimestamps: MapLike = {}; private installRunCount = 1; private inFlightRequestCount = 0; @@ -258,14 +258,14 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Adding entry into typings cache: '${packageName}' => '${typingFile}'`); } - if (this.typeDeclarationTimestamps.get(key) === undefined) { + if (getProperty(this.typeDeclarationTimestamps, key) === undefined) { // getModifiedTime is only undefined if we were to use the ChakraHost, but we never do in this scenario // defaults to old behavior of never updating if we ever use a host without getModifiedTime in the future const timestamp = this.installTypingHost.getModifiedTime === undefined ? Date.now() : this.installTypingHost.getModifiedTime(typingFile).getTime(); - this.typeDeclarationTimestamps.set(key, timestamp); + this.typeDeclarationTimestamps[key] = timestamp; } // timestamp guaranteed to not be undefined by above check - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: this.typeDeclarationTimestamps.get(key) }; + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: getProperty(this.typeDeclarationTimestamps, key) }; this.packageNameToTypingLocation.set(packageName, newTyping); } } @@ -365,11 +365,11 @@ namespace ts.server.typingsInstaller { this.missingTypingsSet.set(packageName, true); continue; } - if (!this.packageNameToTypingLocation.has(packageName)) { - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: Date.now() }; - this.packageNameToTypingLocation.set(packageName, newTyping); - this.typeDeclarationTimestamps.set(packageName, Date.now()); - } + + const newTimestamp = Date.now(); + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: newTimestamp }; + this.packageNameToTypingLocation.set(packageName, newTyping); + this.typeDeclarationTimestamps[packageName] = newTimestamp; installedTypingFiles.push(typingFile); } if (this.log.isEnabled()) { From b0321dc177dffae1bbd7ff020386ee648189b47c Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Fri, 29 Dec 2017 14:21:55 -0800 Subject: [PATCH 03/32] Refactor to avoid errors --- src/server/typingsInstaller/typingsInstaller.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index a3b96a4e02e..22982b60075 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -55,7 +55,7 @@ namespace ts.server.typingsInstaller { try { if (fileExists) { const content = JSON.parse(host.readFile(typeDeclarationTimestampFilePath)); - return content.entries; + return content.entries || {}; } else { host.writeFile(typeDeclarationTimestampFilePath, "{}"); @@ -247,10 +247,11 @@ namespace ts.server.typingsInstaller { continue; } const existingTypingFile = this.packageNameToTypingLocation.get(packageName); - if (existingTypingFile.typingLocation === typingFile) { - continue; - } if (existingTypingFile) { + if (existingTypingFile.typingLocation === typingFile) { + continue; + } + if (this.log.isEnabled()) { this.log.writeLine(`New typing for package ${packageName} from '${typingFile}' conflicts with existing typing file '${existingTypingFile}'`); } From bf4ec1df5ae468a3a8e0b3269d6b461e81656526 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Tue, 2 Jan 2018 16:29:39 -0800 Subject: [PATCH 04/32] Fix timestamp writing, npm install, and cache behavior --- src/server/typingsInstaller/nodeTypingsInstaller.ts | 2 +- src/server/typingsInstaller/typingsInstaller.ts | 13 ++++++++++--- src/services/jsTyping.ts | 12 +++++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 378708a4a81..36f5adab400 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -185,7 +185,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`); } - const command = `${this.npmPath} install@latest --ignore-scripts ${packageNames.join(" ")} --save-dev --force --user-agent="typesInstaller/${version}"`; + const command = `${this.npmPath} install --ignore-scripts ${packageNames.join(" ")} --save-dev --user-agent="typesInstaller/${version}"`; const start = Date.now(); const hasError = this.execSyncAndLog(command, { cwd }); if (this.log.isEnabled()) { diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 22982b60075..cf441017de9 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -19,6 +19,8 @@ namespace ts.server.typingsInstaller { writeLine: noop }; + const timestampsFile = "timestamps.json"; + function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string { try { const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { moduleResolution: ModuleResolutionKind.NodeJs }, installTypingHost); @@ -223,7 +225,7 @@ namespace ts.server.typingsInstaller { } return; } - const timestampJson = combinePaths(cacheLocation, "timestamps.json"); + const timestampJson = combinePaths(cacheLocation, timestampsFile); this.typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampJson, this.installTypingHost, this.log); const packageJson = combinePaths(cacheLocation, "package.json"); if (this.log.isEnabled()) { @@ -264,6 +266,9 @@ namespace ts.server.typingsInstaller { // defaults to old behavior of never updating if we ever use a host without getModifiedTime in the future const timestamp = this.installTypingHost.getModifiedTime === undefined ? Date.now() : this.installTypingHost.getModifiedTime(typingFile).getTime(); this.typeDeclarationTimestamps[key] = timestamp; + if (this.log.isEnabled()) { + this.log.writeLine(`Adding entry into timestamp cache: '${key}' => '${timestamp}'`); + } } // timestamp guaranteed to not be undefined by above check const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: getProperty(this.typeDeclarationTimestamps, key) }; @@ -360,6 +365,7 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Installed typings ${JSON.stringify(scopedTypings)}`); } const installedTypingFiles: string[] = []; + const typesPackageName = (packageName: string) => `@types/${packageName}`; for (const packageName of filteredTypings) { const typingFile = typingToFileName(cachePath, packageName, this.installTypingHost, this.log); if (!typingFile) { @@ -370,7 +376,7 @@ namespace ts.server.typingsInstaller { const newTimestamp = Date.now(); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: newTimestamp }; this.packageNameToTypingLocation.set(packageName, newTyping); - this.typeDeclarationTimestamps[packageName] = newTimestamp; + this.typeDeclarationTimestamps[typesPackageName(packageName)] = newTimestamp; installedTypingFiles.push(typingFile); } if (this.log.isEnabled()) { @@ -378,7 +384,8 @@ namespace ts.server.typingsInstaller { } const newFileContents: TypeDeclarationTimestampFile = { entries: this.typeDeclarationTimestamps }; - writeTypeDeclarationTimestampFile(cachePath, newFileContents, this.installTypingHost, this.log); // WRONG PATH + const timestampJson = combinePaths(cachePath, timestampsFile); + writeTypeDeclarationTimestampFile(timestampJson, newFileContents, this.installTypingHost, this.log); this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); } diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 85660a03368..b26b2a00a84 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -31,10 +31,16 @@ namespace ts.JsTyping { timestamp: number; } - const typingLifetime = new Date(0, 1); - export function isTypingExpired(typing: JsTyping.CachedTyping | undefined) { - return typing && Date.now() - typingLifetime.getTime() < typing.timestamp; + const comparisonDate = new Date(); + const currentMonth = comparisonDate.getMonth(); + if (currentMonth) { + comparisonDate.setMonth(11); + comparisonDate.setFullYear(comparisonDate.getFullYear() - 1); + } else { + comparisonDate.setMonth(currentMonth - 1); + } + return !typing || typing.timestamp < comparisonDate.getTime(); } /* @internal */ From 0b47a2dcfe58cca0dcddb9572a7969ef52ad42e5 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 4 Jan 2018 10:24:37 -0800 Subject: [PATCH 05/32] Add tests --- .../unittests/tsserverProjectSystem.ts | 6 +- src/harness/unittests/typingsInstaller.ts | 161 +++++++++++++++++- src/harness/virtualFileSystemWithWatch.ts | 8 +- src/services/jsTyping.ts | 3 +- 4 files changed, 171 insertions(+), 7 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index fe7a2095b86..74981bbac35 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -243,9 +243,11 @@ namespace ts.projectSystem { } } - export function createSession(host: server.ServerHost, opts: Partial = {}) { + export function createSession(host: TestServerHost, opts: Partial = {}) { if (opts.typingsInstaller === undefined) { - opts.typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/ 5, host); + const globalTypingsCacheLocation = "/a/data"; + host.ensureFileOrFolder({ path: globalTypingsCacheLocation }); + opts.typingsInstaller = new TestTypingsInstaller(globalTypingsCacheLocation, /*throttleLimit*/ 5, host); } if (opts.eventHandler !== undefined) { diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 5c2f8758916..bdb96c2ec9c 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -22,7 +22,8 @@ namespace ts.projectSystem { } class Installer extends TestTypingsInstaller { - constructor(host: server.ServerHost, p?: InstallerParams, log?: TI.Log) { + constructor(host: TestServerHost, p?: InstallerParams, log?: TI.Log) { + host.ensureFileOrFolder({ path: (p && p.globalTypingsCacheLocation) || "/a/data" }); super( (p && p.globalTypingsCacheLocation) || "/a/data", (p && p.throttleLimit) || 5, @@ -1053,6 +1054,132 @@ namespace ts.projectSystem { const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion(); assert.notEqual(version1, version2, "set of unresolved imports should change"); }); + + it("expired cache entry (inferred project, should install typings)", () => { + const file1 = { + path: "/a/b/app.js", + content: "" + }; + const packageJson = { + path: "/a/b/package.json", + content: JSON.stringify({ + name: "test", + dependencies: { + jquery: "^3.1.0" + } + }) + }; + const date = new Date(); + date.setFullYear(date.getFullYear() - 1); + const timestamps = { + path: "/a/data/timestamps.json", + content: JSON.stringify({ + entries: { + "@types/jquery": date.getTime() + } + }) + }; + const jquery = { + path: "/a/data/node_modules/@types/jquery/index.d.ts", + content: "declare const $: { x: number }" + }; + const cacheConfig = { + path: "/a/data/package.json", + content: JSON.stringify({ + dependencies: { + "types-registry": "^0.1.317" + }, + devDependencies: { + "@types/jquery": "^3.2.16" + } + }) + }; + const host = createServerHost([file1, packageJson, jquery, timestamps, cacheConfig]); + const installer = new (class extends Installer { + constructor() { + super(host, { typesRegistry: createTypesRegistry("jquery") }); + } + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { + const installedTypings = ["@types/jquery"]; + const typingFiles = [jquery]; + executeCommand(this, host, installedTypings, typingFiles, cb); + } + })(); + + const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller: installer }); + projectService.openClientFile(file1.path); + + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + const p = projectService.inferredProjects[0]; + checkProjectActualFiles(p, [file1.path]); + + installer.installAll(/*expectedCount*/ 1); + + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkProjectActualFiles(p, [file1.path, jquery.path]); + }); + + it("non-expired cache entry (inferred project, should not install typings)", () => { + const file1 = { + path: "/a/b/app.js", + content: "" + }; + const packageJson = { + path: "/a/b/package.json", + content: JSON.stringify({ + name: "test", + dependencies: { + jquery: "^3.1.0" + } + }) + }; + const timestamps = { + path: "/a/data/timestamps.json", + content: JSON.stringify({ + entries: { + "@types/jquery": Date.now() + } + }) + }; + const cacheConfig = { + path: "/a/data/package.json", + content: JSON.stringify({ + dependencies: { + "types-registry": "^0.1.317" + }, + devDependencies: { + "@types/jquery": "^3.2.16" + } + }) + }; + const jquery = { + path: "/a/data/node_modules/@types/jquery/index.d.ts", + content: "declare const $: { x: number }" + }; + const host = createServerHost([file1, packageJson, timestamps, cacheConfig, jquery]); + const installer = new (class extends Installer { + constructor() { + super(host, { typesRegistry: createTypesRegistry("jquery") }); + } + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { + const installedTypings: string[] = []; + const typingFiles: FileOrFolder[] = []; + executeCommand(this, host, installedTypings, typingFiles, cb); + } + })(); + + const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller: installer }); + projectService.openClientFile(file1.path); + + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + const p = projectService.inferredProjects[0]; + checkProjectActualFiles(p, [file1.path]); + + installer.installAll(/*expectedCount*/ 0); + + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkProjectActualFiles(p, [file1.path]); + }); }); describe("Validate package name:", () => { @@ -1211,6 +1338,38 @@ namespace ts.projectSystem { filesToWatch: ["/bower_components", "/node_modules"], }); }); + + it("should install expired typings", () => { + const date = new Date(); + date.setFullYear(date.getFullYear() - 1); + + const app = { + path: "/a/app.js", + content: "" + }; + const cachePath = "/a/cache/"; + const commander = { + path: cachePath + "node_modules/@types/commander/index.d.ts", + content: "export let x: number" + }; + const node = { + path: cachePath + "node_modules/@types/node/index.d.ts", + content: "export let y: number" + }; + const host = createServerHost([app]); + const cache = createMapFromTemplate({ + node: { typingLocation: node.path, timestamp: Date.now() }, + commander: { typingLocation: commander.path, timestamp: date.getTime() } + }); + const logger = trackingLogger(); + const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, ["http", "commander"]); + assert.deepEqual(logger.finish(), [ + 'Inferred typings from unresolved imports: ["node","commander"]', + 'Result: {"cachedTypingPaths":["/a/cache/node_modules/@types/node/index.d.ts"],"newTypingNames":["commander"],"filesToWatch":["/a/bower_components","/a/node_modules"]}', + ]); + assert.deepEqual(result.cachedTypingPaths, [node.path]); + assert.deepEqual(result.newTypingNames, ["commander"]); + }); }); describe("telemetry events", () => { diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 921d4674231..06e1b45a688 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -383,9 +383,11 @@ interface Array {}` ensureFileOrFolder(fileOrDirectory: FileOrFolder, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean) { if (isString(fileOrDirectory.content)) { const file = this.toFile(fileOrDirectory); - Debug.assert(!this.fs.get(file.path)); - const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath)); - this.addFileOrFolderInFolder(baseFolder, file, ignoreWatchInvokedWithTriggerAsFileCreate); + // file may already exist when updating existing type declaration file + if (!this.fs.get(file.path)) { + const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath)); + this.addFileOrFolderInFolder(baseFolder, file, ignoreWatchInvokedWithTriggerAsFileCreate); + } } else { const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory); diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index b26b2a00a84..f636de25313 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -37,7 +37,8 @@ namespace ts.JsTyping { if (currentMonth) { comparisonDate.setMonth(11); comparisonDate.setFullYear(comparisonDate.getFullYear() - 1); - } else { + } + else { comparisonDate.setMonth(currentMonth - 1); } return !typing || typing.timestamp < comparisonDate.getTime(); From 4c32ac010c5801529727ecbfc79eacc4b21b94b8 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 4 Jan 2018 11:05:39 -0800 Subject: [PATCH 06/32] Add test for timestamps write --- src/harness/unittests/typingsInstaller.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index bdb96c2ec9c..fb82a17b965 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1,6 +1,10 @@ /// /// -/// +/// import { deepEqual } from "assert";import { deepEqual } from "assert"; + + + + namespace ts.projectSystem { import TI = server.typingsInstaller; @@ -1117,6 +1121,7 @@ namespace ts.projectSystem { checkNumberOfProjects(projectService, { inferredProjects: 1 }); checkProjectActualFiles(p, [file1.path, jquery.path]); + assert(host.readFile(timestamps.path) !== JSON.stringify({ entries: { "@types/jquery": date.getTime() } }), "timestamps content should be updated"); }); it("non-expired cache entry (inferred project, should not install typings)", () => { From 3f23d5d02e226d810650432717c0d6425bc059d1 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 4 Jan 2018 14:04:14 -0800 Subject: [PATCH 07/32] Respond to CR --- src/harness/unittests/typingsInstaller.ts | 2 +- .../typingsInstaller/typingsInstaller.ts | 60 ++++++------------- src/services/jsTyping.ts | 12 +--- 3 files changed, 21 insertions(+), 53 deletions(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index fb82a17b965..8636b38d294 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1,6 +1,6 @@ /// /// -/// import { deepEqual } from "assert";import { deepEqual } from "assert"; +/// diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index cf441017de9..291f2b9b871 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -19,7 +19,7 @@ namespace ts.server.typingsInstaller { writeLine: noop }; - const timestampsFile = "timestamps.json"; + const timestampsFileName = "timestamps.json"; function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string { try { @@ -44,60 +44,37 @@ namespace ts.server.typingsInstaller { } interface TypeDeclarationTimestampFile { + // entries maps from package names (e.g. "@types/node") to timestamp values (as produced by Date#getTime) entries: MapLike; } function loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, host: InstallTypingHost, log: Log): MapLike { - const fileExists = host.fileExists(typeDeclarationTimestampFilePath); - if (!fileExists) { - if (log.isEnabled()) { - log.writeLine(`Type declaration timestamp file '${typeDeclarationTimestampFilePath}' does not exist`); - } - } try { - if (fileExists) { - const content = JSON.parse(host.readFile(typeDeclarationTimestampFilePath)); - return content.entries || {}; - } - else { - host.writeFile(typeDeclarationTimestampFilePath, "{}"); - if (log.isEnabled()) { - log.writeLine("Type declaration timestamp file was created."); - } - return {}; + if (log.isEnabled()) { + log.writeLine("Loading type declaration timestamp file."); } + const content = JSON.parse(host.readFile(typeDeclarationTimestampFilePath)); + return content.entries || {}; } catch (e) { if (log.isEnabled()) { log.writeLine(`Error when loading type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); } + // If file cannot be read, we update all requested type declarations. return {}; } } function writeTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, newContents: TypeDeclarationTimestampFile, host: InstallTypingHost, log: Log): void { - const fileExists = host.fileExists(typeDeclarationTimestampFilePath); - if (!fileExists) { - if (log.isEnabled()) { - log.writeLine(`Type declaration timestamp file '${typeDeclarationTimestampFilePath}' does not exist`); - } - } try { - if (fileExists) { - host.writeFile(typeDeclarationTimestampFilePath, JSON.stringify(newContents)); - return; - } - else { - host.writeFile(typeDeclarationTimestampFilePath, JSON.stringify(newContents)); - if (log.isEnabled()) { - log.writeLine("Type declaration time stamp file was created."); - } - return; + if (log.isEnabled()) { + log.writeLine("Writing type declaration timestamp file."); } + host.writeFile(typeDeclarationTimestampFilePath, JSON.stringify(newContents)); } catch (e) { if (log.isEnabled()) { - log.writeLine(`Error when writing new type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); + log.writeLine(`Error when writing type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); } return; } @@ -162,11 +139,12 @@ namespace ts.server.typingsInstaller { } // load existing typing information from the cache + const timestampsFilePath = combinePaths(req.cachePath || this.globalCachePath, timestampsFileName); if (req.cachePath) { if (this.log.isEnabled()) { this.log.writeLine(`Request specifies cache path '${req.cachePath}', loading cached information...`); } - this.processCacheLocation(req.cachePath); + this.processCacheLocation(req.cachePath, timestampsFilePath); } if (this.safeList === undefined) { @@ -191,7 +169,7 @@ namespace ts.server.typingsInstaller { // install typings if (discoverTypingsResult.newTypingNames.length) { - this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames); + this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames, timestampsFilePath); } else { this.sendResponse(this.createSetTypings(req, discoverTypingsResult.cachedTypingPaths)); @@ -215,7 +193,7 @@ namespace ts.server.typingsInstaller { this.safeList = JsTyping.loadSafeList(this.installTypingHost, this.safeListPath); } - private processCacheLocation(cacheLocation: string) { + private processCacheLocation(cacheLocation: string, timestampsFilePath?: string) { if (this.log.isEnabled()) { this.log.writeLine(`Processing cache location '${cacheLocation}'`); } @@ -225,8 +203,7 @@ namespace ts.server.typingsInstaller { } return; } - const timestampJson = combinePaths(cacheLocation, timestampsFile); - this.typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampJson, this.installTypingHost, this.log); + this.typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampsFilePath || combinePaths(cacheLocation, timestampsFileName), this.installTypingHost, this.log); const packageJson = combinePaths(cacheLocation, "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Trying to find '${packageJson}'...`); @@ -321,7 +298,7 @@ namespace ts.server.typingsInstaller { } } - private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { + private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[], timestampsFilePath: string) { if (this.log.isEnabled()) { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } @@ -384,8 +361,7 @@ namespace ts.server.typingsInstaller { } const newFileContents: TypeDeclarationTimestampFile = { entries: this.typeDeclarationTimestamps }; - const timestampJson = combinePaths(cachePath, timestampsFile); - writeTypeDeclarationTimestampFile(timestampJson, newFileContents, this.installTypingHost, this.log); + writeTypeDeclarationTimestampFile(timestampsFilePath, newFileContents, this.installTypingHost, this.log); this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); } diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index f636de25313..335b36952f6 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -32,16 +32,8 @@ namespace ts.JsTyping { } export function isTypingExpired(typing: JsTyping.CachedTyping | undefined) { - const comparisonDate = new Date(); - const currentMonth = comparisonDate.getMonth(); - if (currentMonth) { - comparisonDate.setMonth(11); - comparisonDate.setFullYear(comparisonDate.getFullYear() - 1); - } - else { - comparisonDate.setMonth(currentMonth - 1); - } - return !typing || typing.timestamp < comparisonDate.getTime(); + const msPerMonth = 1000 * 60 * 60 * 24 * 30; // ms/second * second/minute * minutes/hour * hours/day * days/month + return !typing || typing.timestamp < Date.now() - msPerMonth; } /* @internal */ From 7b6be118f5653c57d83a8e511d3d518454c03ce8 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 4 Jan 2018 15:21:54 -0800 Subject: [PATCH 08/32] Allow for local timestamp files and style fixes --- src/harness/unittests/typingsInstaller.ts | 4 --- .../typingsInstaller/typingsInstaller.ts | 27 ++++++++++--------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 8636b38d294..e76f75f45d9 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -2,10 +2,6 @@ /// /// - - - - namespace ts.projectSystem { import TI = server.typingsInstaller; import validatePackageName = JsTyping.validatePackageName; diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 291f2b9b871..4996d0d29a1 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -76,7 +76,6 @@ namespace ts.server.typingsInstaller { if (log.isEnabled()) { log.writeLine(`Error when writing type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); } - return; } } @@ -87,7 +86,7 @@ namespace ts.server.typingsInstaller { private readonly projectWatchers: Map = createMap(); private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; - private typeDeclarationTimestamps: MapLike = {}; + private globalTypeDeclarationTimestamps: MapLike = {}; private installRunCount = 1; private inFlightRequestCount = 0; @@ -104,7 +103,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}', types map path ${typesMapLocation}`); } - this.processCacheLocation(this.globalCachePath); + this.globalTypeDeclarationTimestamps = this.processCacheLocation(this.globalCachePath); } closeProject(req: CloseProject) { @@ -140,11 +139,12 @@ namespace ts.server.typingsInstaller { // load existing typing information from the cache const timestampsFilePath = combinePaths(req.cachePath || this.globalCachePath, timestampsFileName); + let localTimestamps: MapLike; if (req.cachePath) { if (this.log.isEnabled()) { this.log.writeLine(`Request specifies cache path '${req.cachePath}', loading cached information...`); } - this.processCacheLocation(req.cachePath, timestampsFilePath); + localTimestamps = this.processCacheLocation(req.cachePath, timestampsFilePath); } if (this.safeList === undefined) { @@ -169,7 +169,7 @@ namespace ts.server.typingsInstaller { // install typings if (discoverTypingsResult.newTypingNames.length) { - this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames, timestampsFilePath); + this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames, timestampsFilePath, localTimestamps || this.globalTypeDeclarationTimestamps); } else { this.sendResponse(this.createSetTypings(req, discoverTypingsResult.cachedTypingPaths)); @@ -193,7 +193,7 @@ namespace ts.server.typingsInstaller { this.safeList = JsTyping.loadSafeList(this.installTypingHost, this.safeListPath); } - private processCacheLocation(cacheLocation: string, timestampsFilePath?: string) { + private processCacheLocation(cacheLocation: string, timestampsFilePath?: string): MapLike { if (this.log.isEnabled()) { this.log.writeLine(`Processing cache location '${cacheLocation}'`); } @@ -203,7 +203,7 @@ namespace ts.server.typingsInstaller { } return; } - this.typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampsFilePath || combinePaths(cacheLocation, timestampsFileName), this.installTypingHost, this.log); + const typeDeclarationTimestamps: MapLike = loadTypeDeclarationTimestampFile(timestampsFilePath || combinePaths(cacheLocation, timestampsFileName), this.installTypingHost, this.log); const packageJson = combinePaths(cacheLocation, "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Trying to find '${packageJson}'...`); @@ -238,17 +238,17 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Adding entry into typings cache: '${packageName}' => '${typingFile}'`); } - if (getProperty(this.typeDeclarationTimestamps, key) === undefined) { + if (getProperty(typeDeclarationTimestamps, key) === undefined) { // getModifiedTime is only undefined if we were to use the ChakraHost, but we never do in this scenario // defaults to old behavior of never updating if we ever use a host without getModifiedTime in the future const timestamp = this.installTypingHost.getModifiedTime === undefined ? Date.now() : this.installTypingHost.getModifiedTime(typingFile).getTime(); - this.typeDeclarationTimestamps[key] = timestamp; + typeDeclarationTimestamps[key] = timestamp; if (this.log.isEnabled()) { this.log.writeLine(`Adding entry into timestamp cache: '${key}' => '${timestamp}'`); } } // timestamp guaranteed to not be undefined by above check - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: getProperty(this.typeDeclarationTimestamps, key) }; + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: getProperty(typeDeclarationTimestamps, key) }; this.packageNameToTypingLocation.set(packageName, newTyping); } } @@ -257,6 +257,7 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Finished processing cache location '${cacheLocation}'`); } this.knownCachesSet.set(cacheLocation, true); + return typeDeclarationTimestamps; } private filterTypings(typingsToInstall: ReadonlyArray): ReadonlyArray { @@ -298,7 +299,7 @@ namespace ts.server.typingsInstaller { } } - private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[], timestampsFilePath: string) { + private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[], timestampsFilePath: string, typeDeclarationTimestamps: MapLike) { if (this.log.isEnabled()) { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } @@ -353,14 +354,14 @@ namespace ts.server.typingsInstaller { const newTimestamp = Date.now(); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: newTimestamp }; this.packageNameToTypingLocation.set(packageName, newTyping); - this.typeDeclarationTimestamps[typesPackageName(packageName)] = newTimestamp; + typeDeclarationTimestamps[typesPackageName(packageName)] = newTimestamp; installedTypingFiles.push(typingFile); } if (this.log.isEnabled()) { this.log.writeLine(`Installed typing files ${JSON.stringify(installedTypingFiles)}`); } - const newFileContents: TypeDeclarationTimestampFile = { entries: this.typeDeclarationTimestamps }; + const newFileContents: TypeDeclarationTimestampFile = { entries: typeDeclarationTimestamps }; writeTypeDeclarationTimestampFile(timestampsFilePath, newFileContents, this.installTypingHost, this.log); this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); From 6a16cfe0a5dcfe38b13beaf6396bae99149f8950 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 4 Jan 2018 16:44:01 -0800 Subject: [PATCH 09/32] Use existing map to hold representations of timestamp files --- .../typingsInstaller/typingsInstaller.ts | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 4996d0d29a1..d3952ee13b0 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -19,8 +19,6 @@ namespace ts.server.typingsInstaller { writeLine: noop }; - const timestampsFileName = "timestamps.json"; - function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string { try { const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { moduleResolution: ModuleResolutionKind.NodeJs }, installTypingHost); @@ -43,12 +41,14 @@ namespace ts.server.typingsInstaller { onRequestCompleted: RequestCompletedAction; } + const timestampsFileName = "timestamps.json"; + type TypingsTimestamps = MapLike; interface TypeDeclarationTimestampFile { // entries maps from package names (e.g. "@types/node") to timestamp values (as produced by Date#getTime) - entries: MapLike; + entries: TypingsTimestamps; } - function loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, host: InstallTypingHost, log: Log): MapLike { + function loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, host: InstallTypingHost, log: Log): TypingsTimestamps { try { if (log.isEnabled()) { log.writeLine("Loading type declaration timestamp file."); @@ -82,11 +82,10 @@ namespace ts.server.typingsInstaller { export abstract class TypingsInstaller { private readonly packageNameToTypingLocation: Map = createMap(); private readonly missingTypingsSet: Map = createMap(); - private readonly knownCachesSet: Map = createMap(); + private readonly knownCacheToTimestamps: Map = createMap(); private readonly projectWatchers: Map = createMap(); private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; - private globalTypeDeclarationTimestamps: MapLike = {}; private installRunCount = 1; private inFlightRequestCount = 0; @@ -103,7 +102,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}', types map path ${typesMapLocation}`); } - this.globalTypeDeclarationTimestamps = this.processCacheLocation(this.globalCachePath); + this.processCacheLocation(this.globalCachePath); } closeProject(req: CloseProject) { @@ -139,12 +138,11 @@ namespace ts.server.typingsInstaller { // load existing typing information from the cache const timestampsFilePath = combinePaths(req.cachePath || this.globalCachePath, timestampsFileName); - let localTimestamps: MapLike; if (req.cachePath) { if (this.log.isEnabled()) { this.log.writeLine(`Request specifies cache path '${req.cachePath}', loading cached information...`); } - localTimestamps = this.processCacheLocation(req.cachePath, timestampsFilePath); + this.processCacheLocation(req.cachePath, timestampsFilePath); } if (this.safeList === undefined) { @@ -169,7 +167,7 @@ namespace ts.server.typingsInstaller { // install typings if (discoverTypingsResult.newTypingNames.length) { - this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames, timestampsFilePath, localTimestamps || this.globalTypeDeclarationTimestamps); + this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames, timestampsFilePath); } else { this.sendResponse(this.createSetTypings(req, discoverTypingsResult.cachedTypingPaths)); @@ -193,17 +191,17 @@ namespace ts.server.typingsInstaller { this.safeList = JsTyping.loadSafeList(this.installTypingHost, this.safeListPath); } - private processCacheLocation(cacheLocation: string, timestampsFilePath?: string): MapLike { + private processCacheLocation(cacheLocation: string, timestampsFilePath?: string) { if (this.log.isEnabled()) { this.log.writeLine(`Processing cache location '${cacheLocation}'`); } - if (this.knownCachesSet.get(cacheLocation)) { + if (this.knownCacheToTimestamps.has(cacheLocation)) { if (this.log.isEnabled()) { this.log.writeLine(`Cache location was already processed...`); } return; } - const typeDeclarationTimestamps: MapLike = loadTypeDeclarationTimestampFile(timestampsFilePath || combinePaths(cacheLocation, timestampsFileName), this.installTypingHost, this.log); + const typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampsFilePath || combinePaths(cacheLocation, timestampsFileName), this.installTypingHost, this.log); const packageJson = combinePaths(cacheLocation, "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Trying to find '${packageJson}'...`); @@ -256,8 +254,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Finished processing cache location '${cacheLocation}'`); } - this.knownCachesSet.set(cacheLocation, true); - return typeDeclarationTimestamps; + this.knownCacheToTimestamps.set(cacheLocation, typeDeclarationTimestamps); } private filterTypings(typingsToInstall: ReadonlyArray): ReadonlyArray { @@ -299,7 +296,7 @@ namespace ts.server.typingsInstaller { } } - private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[], timestampsFilePath: string, typeDeclarationTimestamps: MapLike) { + private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[], timestampsFilePath: string) { if (this.log.isEnabled()) { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } @@ -342,6 +339,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Installed typings ${JSON.stringify(scopedTypings)}`); } + const typeDeclarationTimestamps = this.knownCacheToTimestamps.get(cachePath); const installedTypingFiles: string[] = []; const typesPackageName = (packageName: string) => `@types/${packageName}`; for (const packageName of filteredTypings) { @@ -363,6 +361,7 @@ namespace ts.server.typingsInstaller { const newFileContents: TypeDeclarationTimestampFile = { entries: typeDeclarationTimestamps }; writeTypeDeclarationTimestampFile(timestampsFilePath, newFileContents, this.installTypingHost, this.log); + this.knownCacheToTimestamps.set(cachePath, typeDeclarationTimestamps); this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); } From 23324345e2fcb81c9c297c8937a1bcc1cc072750 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Fri, 5 Jan 2018 14:15:52 -0800 Subject: [PATCH 10/32] Update representation of timestamp file to prevent some extra install calls --- .../typingsInstaller/typingsInstaller.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index d3952ee13b0..15a8b1268ac 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -65,6 +65,20 @@ namespace ts.server.typingsInstaller { } } + function updateTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, timestampsInProcess: TypingsTimestamps, host: InstallTypingHost, log: Log): TypingsTimestamps { + const timestampsOnDisk = loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath, host, log); + for (const packageName in timestampsOnDisk) { + const timestampForPackageInProcess = getProperty(timestampsInProcess, packageName); + if (timestampForPackageInProcess) { + timestampsInProcess[packageName] = Math.max(timestampForPackageInProcess, timestampsOnDisk[packageName]); + } + else { + timestampsInProcess[packageName] = timestampsOnDisk[packageName]; + } + } + return timestampsInProcess; + } + function writeTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, newContents: TypeDeclarationTimestampFile, host: InstallTypingHost, log: Log): void { try { if (log.isEnabled()) { @@ -359,9 +373,10 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Installed typing files ${JSON.stringify(installedTypingFiles)}`); } - const newFileContents: TypeDeclarationTimestampFile = { entries: typeDeclarationTimestamps }; + const updatedTypeDeclarationTimestamps = updateTypeDeclarationTimestampFile(timestampsFilePath, typeDeclarationTimestamps, this.installTypingHost, this.log); + const newFileContents: TypeDeclarationTimestampFile = { entries: updatedTypeDeclarationTimestamps }; writeTypeDeclarationTimestampFile(timestampsFilePath, newFileContents, this.installTypingHost, this.log); - this.knownCacheToTimestamps.set(cachePath, typeDeclarationTimestamps); + this.knownCacheToTimestamps.set(cachePath, updatedTypeDeclarationTimestamps); this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); } From e72ea6f7b1e6e3314b089e7a962a61311cdb4cf7 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 11 Jan 2018 09:13:33 -0800 Subject: [PATCH 11/32] Update installed types if older than those listed in the registry --- .../unittests/tsserverProjectSystem.ts | 2 +- src/harness/unittests/typingsInstaller.ts | 54 ++++++++++++++---- src/server/server.ts | 2 +- src/server/types.ts | 2 +- .../typingsInstaller/nodeTypingsInstaller.ts | 12 ++-- .../typingsInstaller/typingsInstaller.ts | 35 +++++++++--- src/services/jsTyping.ts | 4 +- src/services/semver.ts | 55 +++++++++++++++++++ src/services/tsconfig.json | 1 + 9 files changed, 137 insertions(+), 30 deletions(-) create mode 100644 src/services/semver.ts diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 74981bbac35..2c5d4c59bab 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -63,7 +63,7 @@ namespace ts.projectSystem { readonly globalTypingsCacheLocation: string, throttleLimit: number, installTypingHost: server.ServerHost, - readonly typesRegistry = createMap(), + readonly typesRegistry = createMap>(), log?: TI.Log) { super(installTypingHost, globalTypingsCacheLocation, safeList.path, customTypesMap.path, throttleLimit, log); } diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index e76f75f45d9..cbeab8f7a97 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1,6 +1,7 @@ /// /// /// +/// namespace ts.projectSystem { import TI = server.typingsInstaller; @@ -10,13 +11,24 @@ namespace ts.projectSystem { interface InstallerParams { globalTypingsCacheLocation?: string; throttleLimit?: number; - typesRegistry?: Map; + typesRegistry?: Map>; } - function createTypesRegistry(...list: string[]): Map { - const map = createMap(); + function createTypesRegistry(...list: string[]): Map> { + const versionMap = { + "latest": "1.3.0", + "ts2.0": "1.0.0", + "ts2.1": "1.0.0", + "ts2.2": "1.2.0", + "ts2.3": "1.3.0", + "ts2.4": "1.3.0", + "ts2.5": "1.3.0", + "ts2.6": "1.3.0", + "ts2.7": "1.3.0" + }; + const map = createMap>(); for (const l of list) { - map.set(l, undefined); + map.set(l, versionMap); } return map; } @@ -51,7 +63,7 @@ namespace ts.projectSystem { const logs: string[] = []; return { log(message) { - logs.push(message); + logs.push(message); }, finish() { return logs; @@ -1149,7 +1161,17 @@ namespace ts.projectSystem { "types-registry": "^0.1.317" }, devDependencies: { - "@types/jquery": "^3.2.16" + "@types/jquery": "^1.3.0" + } + }) + }; + const cacheLockConfig = { + path: "/a/data/package-lock.json", + content: JSON.stringify({ + dependencies: { + "@types/jquery": { + version: "1.3.0" + } } }) }; @@ -1157,7 +1179,7 @@ namespace ts.projectSystem { path: "/a/data/node_modules/@types/jquery/index.d.ts", content: "declare const $: { x: number }" }; - const host = createServerHost([file1, packageJson, timestamps, cacheConfig, jquery]); + const host = createServerHost([file1, packageJson, timestamps, cacheConfig, cacheLockConfig, jquery]); const installer = new (class extends Installer { constructor() { super(host, { typesRegistry: createTypesRegistry("jquery") }); @@ -1299,7 +1321,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f, node]); - const cache = createMapFromTemplate({ node: { typingLocation: node.path, timestamp: Date.now() } }); + const cache = createMapFromTemplate({ node: { typingLocation: node.path, timestamp: Date.now(), version: new Semver(1, 0, 0, /*isPrerelease*/ false) } }); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"]); assert.deepEqual(logger.finish(), [ @@ -1359,8 +1381,8 @@ namespace ts.projectSystem { }; const host = createServerHost([app]); const cache = createMapFromTemplate({ - node: { typingLocation: node.path, timestamp: Date.now() }, - commander: { typingLocation: commander.path, timestamp: date.getTime() } + node: { typingLocation: node.path, timestamp: Date.now(), version: new Semver(1, 0, 0, /*isPrerelease*/ false) }, + commander: { typingLocation: commander.path, timestamp: date.getTime(), version: new Semver(1, 0, 0, /*isPrerelease*/ false) } }); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, ["http", "commander"]); @@ -1433,12 +1455,22 @@ namespace ts.projectSystem { path: "/a/package.json", content: JSON.stringify({ dependencies: { commander: "1.0.0" } }) }; + const packageLockFile = { + path: "/a/cache/package-lock.json", + content: JSON.stringify({ + dependencies: { + "@types/commander": { + version: "1.0.0" + } + } + }) + }; const cachePath = "/a/cache/"; const commander = { path: cachePath + "node_modules/@types/commander/index.d.ts", content: "export let x: number" }; - const host = createServerHost([f1, packageFile]); + const host = createServerHost([f1, packageFile, packageLockFile]); let beginEvent: server.BeginInstallTypes; let endEvent: server.EndInstallTypes; const installer = new (class extends Installer { diff --git a/src/server/server.ts b/src/server/server.ts index 8e53c4d5109..6d5dfafbe8e 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -252,7 +252,7 @@ namespace ts.server { private requestMap = createMap(); // Maps operation ID to newest requestQueue entry with that ID /** We will lazily request the types registry on the first call to `isKnownTypesPackageName` and store it in `typesRegistryCache`. */ private requestedRegistry: boolean; - private typesRegistryCache: Map | undefined; + private typesRegistryCache: Map> | undefined; // This number is essentially arbitrary. Processing more than one typings request // at a time makes sense, but having too many in the pipe results in a hang diff --git a/src/server/types.ts b/src/server/types.ts index 69b1dae0d7c..161fb00a6ae 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -77,7 +77,7 @@ declare namespace ts.server { /* @internal */ export interface TypesRegistryResponse extends TypingInstallerResponse { readonly kind: EventTypesRegistry; - readonly typesRegistry: MapLike; + readonly typesRegistry: MapLike>; } export interface PackageInstalledResponse extends ProjectResponse { diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 36f5adab400..e51ec68561c 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -41,15 +41,15 @@ namespace ts.server.typingsInstaller { } interface TypesRegistryFile { - entries: MapLike; + entries: MapLike>; } - function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypingHost, log: Log): Map { + function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypingHost, log: Log): Map> { if (!host.fileExists(typesRegistryFilePath)) { if (log.isEnabled()) { log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`); } - return createMap(); + return createMap>(); } try { const content = JSON.parse(host.readFile(typesRegistryFilePath)); @@ -59,7 +59,7 @@ namespace ts.server.typingsInstaller { if (log.isEnabled()) { log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(e).message}, ${(e).stack}`); } - return createMap(); + return createMap>(); } } @@ -77,7 +77,7 @@ namespace ts.server.typingsInstaller { export class NodeTypingsInstaller extends TypingsInstaller { private readonly nodeExecSync: ExecSync; private readonly npmPath: string; - readonly typesRegistry: Map; + readonly typesRegistry: Map>; private delayedInitializationError: InitializationFailedResponse | undefined; @@ -141,7 +141,7 @@ namespace ts.server.typingsInstaller { this.closeProject(req); break; case "typesRegistry": { - const typesRegistry: { [key: string]: void } = {}; + const typesRegistry: { [key: string]: MapLike } = {}; this.typesRegistry.forEach((value, key) => { typesRegistry[key] = value; }); diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 15a8b1268ac..f3048795229 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -1,6 +1,7 @@ /// /// /// +/// /// /// @@ -9,6 +10,10 @@ namespace ts.server.typingsInstaller { devDependencies: MapLike; } + interface NpmLock { + dependencies: { [packageName: string]: { version: string } }; + } + export interface Log { isEnabled(): boolean; writeLine(text: string): void; @@ -104,7 +109,7 @@ namespace ts.server.typingsInstaller { private installRunCount = 1; private inFlightRequestCount = 0; - abstract readonly typesRegistry: Map; + abstract readonly typesRegistry: Map>; constructor( protected readonly installTypingHost: InstallTypingHost, @@ -217,15 +222,18 @@ namespace ts.server.typingsInstaller { } const typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampsFilePath || combinePaths(cacheLocation, timestampsFileName), this.installTypingHost, this.log); const packageJson = combinePaths(cacheLocation, "package.json"); + const packageLockJson = combinePaths(cacheLocation, "package-lock.json"); if (this.log.isEnabled()) { this.log.writeLine(`Trying to find '${packageJson}'...`); } - if (this.installTypingHost.fileExists(packageJson)) { + if (this.installTypingHost.fileExists(packageJson) && this.installTypingHost.fileExists(packageLockJson)) { const npmConfig = JSON.parse(this.installTypingHost.readFile(packageJson)); + const npmLock = JSON.parse(this.installTypingHost.readFile(packageLockJson)); if (this.log.isEnabled()) { this.log.writeLine(`Loaded content of '${packageJson}': ${JSON.stringify(npmConfig)}`); + this.log.writeLine(`Loaded content of '${packageLockJson}'`); } - if (npmConfig.devDependencies) { + if (npmConfig.devDependencies && npmLock.dependencies) { for (const key in npmConfig.devDependencies) { // key is @types/ const packageName = getBaseFileName(key); @@ -259,8 +267,11 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Adding entry into timestamp cache: '${key}' => '${timestamp}'`); } } + const info = getProperty(npmLock.dependencies, key); + const version = info && info.version; + const semver = Semver.parse(version); // timestamp guaranteed to not be undefined by above check - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: getProperty(typeDeclarationTimestamps, key) }; + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: getProperty(typeDeclarationTimestamps, key), version: semver }; this.packageNameToTypingLocation.set(packageName, newTyping); } } @@ -277,10 +288,6 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) this.log.writeLine(`'${typing}' is in missingTypingsSet - skipping...`); return false; } - if (this.packageNameToTypingLocation.get(typing) && !JsTyping.isTypingExpired(this.packageNameToTypingLocation.get(typing))) { - if (this.log.isEnabled()) this.log.writeLine(`'${typing}' already has a typing - skipping...`); - return false; - } const validationResult = JsTyping.validatePackageName(typing); if (validationResult !== JsTyping.PackageNameValidationResult.Ok) { // add typing name to missing set so we won't process it again @@ -292,8 +299,17 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) this.log.writeLine(`Entry for package '${typing}' does not exist in local types registry - skipping...`); return false; } + if (this.packageNameToTypingLocation.get(typing) && isTypingUpToDate(this.packageNameToTypingLocation.get(typing), this.typesRegistry.get(typing))) { + if (this.log.isEnabled()) this.log.writeLine(`'${typing}' already has an up-to-date typing - skipping...`); + return false; + } return true; }); + + function isTypingUpToDate(cachedTyping: JsTyping.CachedTyping, availableTypingVersions: MapLike) { + const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${ts.version}`)); + return !availableVersion.greaterThan(cachedTyping.version); + } } protected ensurePackageDirectoryExists(directory: string) { @@ -364,7 +380,8 @@ namespace ts.server.typingsInstaller { } const newTimestamp = Date.now(); - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: newTimestamp }; + const newVersion = Semver.parse(this.typesRegistry.get(packageName)[`ts${ts.versionMajorMinor}`]); + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: newTimestamp, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); typeDeclarationTimestamps[typesPackageName(packageName)] = newTimestamp; installedTypingFiles.push(typingFile); diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 335b36952f6..75df1a7ea1b 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -4,6 +4,7 @@ /// /// /// +/// /* @internal */ namespace ts.JsTyping { @@ -29,6 +30,7 @@ namespace ts.JsTyping { export interface CachedTyping { typingLocation: string; timestamp: number; + version: Semver; } export function isTypingExpired(typing: JsTyping.CachedTyping | undefined) { @@ -70,7 +72,7 @@ namespace ts.JsTyping { * @param fileNames are the file names that belong to the same project * @param projectRootPath is the path to the project root directory * @param safeListPath is the path used to retrieve the safe list - * @param packageNameToTypingLocation is the map of package names to their cached typing locations and time of caching + * @param packageNameToTypingLocation is the map of package names to their cached typing locations and time of caching and versions * @param typeAcquisition is used to customize the typing acquisition process * @param compilerOptions are used as a source for typing inference */ diff --git a/src/services/semver.ts b/src/services/semver.ts new file mode 100644 index 00000000000..1f2d8e3de45 --- /dev/null +++ b/src/services/semver.ts @@ -0,0 +1,55 @@ +/* @internal */ +namespace ts { + function intOfString(str: string): number { + const n = parseInt(str, 10); + if (isNaN(n)) { + throw new Error(`Error in parseInt(${JSON.stringify(str)})`); + } + return n; + } + + export class Semver { + static parse(semver: string): Semver { + const isPrerelease = /^(.*)-next.\d+/.test(semver); + const result = Semver.tryParse(semver, isPrerelease); + if (!result) { + throw new Error(`Unexpected semver: ${semver} (isPrerelease: ${isPrerelease})`); + } + return result; + } + + static fromRaw({ major, minor, patch, isPrerelease }: Semver): Semver { + return new Semver(major, minor, patch, isPrerelease); + } + + // This must parse the output of `versionString`. + static tryParse(semver: string, isPrerelease: boolean): Semver | undefined { + // Per the semver spec : + // "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes." + const rgx = isPrerelease ? /^(\d+)\.(\d+)\.0-next.(\d+)$/ : /^(\d+)\.(\d+)\.(\d+)$/; + const match = rgx.exec(semver); + return match ? new Semver(intOfString(match[1]), intOfString(match[2]), intOfString(match[3]), isPrerelease) : undefined; + } + + constructor( + readonly major: number, readonly minor: number, readonly patch: number, + /** + * If true, this is `major.minor.0-next.patch`. + * If false, this is `major.minor.patch`. + */ + readonly isPrerelease: boolean) { } + + get versionString(): string { + return this.isPrerelease ? `${this.major}.${this.minor}.0-next.${this.patch}` : `${this.major}.${this.minor}.${this.patch}`; + } + + equals(sem: Semver): boolean { + return this.major === sem.major && this.minor === sem.minor && this.patch === sem.patch && this.isPrerelease === sem.isPrerelease; + } + + greaterThan(sem: Semver): boolean { + return this.major > sem.major || this.major === sem.major + && (this.minor > sem.minor || this.minor === sem.minor && this.patch > sem.patch); + } + } +} \ No newline at end of file diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index d73014a93a2..a0a81f0042c 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -61,6 +61,7 @@ "services.ts", "transform.ts", "transpile.ts", + "semver.ts", "shims.ts", "signatureHelp.ts", "symbolDisplay.ts", From a21f73f862e354d0a4b79322dc497bd588624d70 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 11 Jan 2018 11:11:26 -0800 Subject: [PATCH 12/32] Remove timestamp checking and move registry check into jstyping --- src/harness/unittests/typingsInstaller.ts | 46 ++++---- src/server/types.ts | 1 - .../typingsInstaller/typingsInstaller.ts | 101 +++--------------- src/services/jsTyping.ts | 15 +-- src/services/shims.ts | 6 +- 5 files changed, 46 insertions(+), 123 deletions(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index cbeab8f7a97..cf3d82ca3d7 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1081,16 +1081,6 @@ namespace ts.projectSystem { } }) }; - const date = new Date(); - date.setFullYear(date.getFullYear() - 1); - const timestamps = { - path: "/a/data/timestamps.json", - content: JSON.stringify({ - entries: { - "@types/jquery": date.getTime() - } - }) - }; const jquery = { path: "/a/data/node_modules/@types/jquery/index.d.ts", content: "declare const $: { x: number }" @@ -1102,11 +1092,21 @@ namespace ts.projectSystem { "types-registry": "^0.1.317" }, devDependencies: { - "@types/jquery": "^3.2.16" + "@types/jquery": "^1.0.0" } }) }; - const host = createServerHost([file1, packageJson, jquery, timestamps, cacheConfig]); + const cacheLockConfig = { + path: "/a/data/package-lock.json", + content: JSON.stringify({ + dependencies: { + "@types/jquery": { + version: "1.0.0" + } + } + }) + }; + const host = createServerHost([file1, packageJson, jquery, cacheConfig, cacheLockConfig]); const installer = new (class extends Installer { constructor() { super(host, { typesRegistry: createTypesRegistry("jquery") }); @@ -1129,7 +1129,6 @@ namespace ts.projectSystem { checkNumberOfProjects(projectService, { inferredProjects: 1 }); checkProjectActualFiles(p, [file1.path, jquery.path]); - assert(host.readFile(timestamps.path) !== JSON.stringify({ entries: { "@types/jquery": date.getTime() } }), "timestamps content should be updated"); }); it("non-expired cache entry (inferred project, should not install typings)", () => { @@ -1282,7 +1281,7 @@ namespace ts.projectSystem { const host = createServerHost([app, jquery, chroma]); const logger = trackingLogger(); - const result = JsTyping.discoverTypings(host, logger.log, [app.path, jquery.path, chroma.path], getDirectoryPath(app.path), safeList, emptyMap, { enable: true }, emptyArray); + const result = JsTyping.discoverTypings(host, logger.log, [app.path, jquery.path, chroma.path], getDirectoryPath(app.path), safeList, emptyMap, { enable: true }, emptyArray, emptyMap); const finish = logger.finish(); assert.deepEqual(finish, [ 'Inferred typings from file names: ["jquery","chroma-js"]', @@ -1302,7 +1301,7 @@ namespace ts.projectSystem { for (const name of JsTyping.nodeCoreModuleList) { const logger = trackingLogger(); - const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, [name, "somename"]); + const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, [name, "somename"], emptyMap); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","somename"]', 'Result: {"cachedTypingPaths":[],"newTypingNames":["node","somename"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', @@ -1321,9 +1320,10 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f, node]); - const cache = createMapFromTemplate({ node: { typingLocation: node.path, timestamp: Date.now(), version: new Semver(1, 0, 0, /*isPrerelease*/ false) } }); + const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: new Semver(1, 3, 0, /*isPrerelease*/ false) } }); + const registry = createTypesRegistry("node"); const logger = trackingLogger(); - const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"]); + const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"], registry); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","bar"]', 'Result: {"cachedTypingPaths":["/a/b/node.d.ts"],"newTypingNames":["bar"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', @@ -1348,7 +1348,7 @@ namespace ts.projectSystem { const host = createServerHost([app, a, b]); const cache = createMap(); const logger = trackingLogger(); - const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, /*unresolvedImports*/ []); + const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, /*unresolvedImports*/ [], emptyMap); assert.deepEqual(logger.finish(), [ 'Searching for typing names in /node_modules; all files: ["/node_modules/a/package.json"]', ' Found package names: ["a"]', @@ -1363,9 +1363,6 @@ namespace ts.projectSystem { }); it("should install expired typings", () => { - const date = new Date(); - date.setFullYear(date.getFullYear() - 1); - const app = { path: "/a/app.js", content: "" @@ -1381,11 +1378,12 @@ namespace ts.projectSystem { }; const host = createServerHost([app]); const cache = createMapFromTemplate({ - node: { typingLocation: node.path, timestamp: Date.now(), version: new Semver(1, 0, 0, /*isPrerelease*/ false) }, - commander: { typingLocation: commander.path, timestamp: date.getTime(), version: new Semver(1, 0, 0, /*isPrerelease*/ false) } + node: { typingLocation: node.path, version: new Semver(1, 3, 0, /*isPrerelease*/ false) }, + commander: { typingLocation: commander.path, version: new Semver(1, 0, 0, /*isPrerelease*/ false) } }); + const registry = createTypesRegistry("node", "commander"); const logger = trackingLogger(); - const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, ["http", "commander"]); + const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, ["http", "commander"], registry); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","commander"]', 'Result: {"cachedTypingPaths":["/a/cache/node_modules/@types/node/index.d.ts"],"newTypingNames":["commander"],"filesToWatch":["/a/bower_components","/a/node_modules"]}', diff --git a/src/server/types.ts b/src/server/types.ts index 161fb00a6ae..6f773955d45 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -128,6 +128,5 @@ declare namespace ts.server { writeFile(path: string, content: string): void; createDirectory(path: string): void; watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; - getModifiedTime?(path: string): Date; } } \ No newline at end of file diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index f3048795229..18890d8af05 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -46,62 +46,10 @@ namespace ts.server.typingsInstaller { onRequestCompleted: RequestCompletedAction; } - const timestampsFileName = "timestamps.json"; - type TypingsTimestamps = MapLike; - interface TypeDeclarationTimestampFile { - // entries maps from package names (e.g. "@types/node") to timestamp values (as produced by Date#getTime) - entries: TypingsTimestamps; - } - - function loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, host: InstallTypingHost, log: Log): TypingsTimestamps { - try { - if (log.isEnabled()) { - log.writeLine("Loading type declaration timestamp file."); - } - const content = JSON.parse(host.readFile(typeDeclarationTimestampFilePath)); - return content.entries || {}; - } - catch (e) { - if (log.isEnabled()) { - log.writeLine(`Error when loading type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); - } - // If file cannot be read, we update all requested type declarations. - return {}; - } - } - - function updateTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, timestampsInProcess: TypingsTimestamps, host: InstallTypingHost, log: Log): TypingsTimestamps { - const timestampsOnDisk = loadTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath, host, log); - for (const packageName in timestampsOnDisk) { - const timestampForPackageInProcess = getProperty(timestampsInProcess, packageName); - if (timestampForPackageInProcess) { - timestampsInProcess[packageName] = Math.max(timestampForPackageInProcess, timestampsOnDisk[packageName]); - } - else { - timestampsInProcess[packageName] = timestampsOnDisk[packageName]; - } - } - return timestampsInProcess; - } - - function writeTypeDeclarationTimestampFile(typeDeclarationTimestampFilePath: string, newContents: TypeDeclarationTimestampFile, host: InstallTypingHost, log: Log): void { - try { - if (log.isEnabled()) { - log.writeLine("Writing type declaration timestamp file."); - } - host.writeFile(typeDeclarationTimestampFilePath, JSON.stringify(newContents)); - } - catch (e) { - if (log.isEnabled()) { - log.writeLine(`Error when writing type declaration timestamp file '${typeDeclarationTimestampFilePath}': ${(e).message}, ${(e).stack}`); - } - } - } - export abstract class TypingsInstaller { private readonly packageNameToTypingLocation: Map = createMap(); private readonly missingTypingsSet: Map = createMap(); - private readonly knownCacheToTimestamps: Map = createMap(); + private readonly knownCachesSet: Map = createMap(); private readonly projectWatchers: Map = createMap(); private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; @@ -156,12 +104,11 @@ namespace ts.server.typingsInstaller { } // load existing typing information from the cache - const timestampsFilePath = combinePaths(req.cachePath || this.globalCachePath, timestampsFileName); if (req.cachePath) { if (this.log.isEnabled()) { this.log.writeLine(`Request specifies cache path '${req.cachePath}', loading cached information...`); } - this.processCacheLocation(req.cachePath, timestampsFilePath); + this.processCacheLocation(req.cachePath); } if (this.safeList === undefined) { @@ -175,7 +122,8 @@ namespace ts.server.typingsInstaller { this.safeList, this.packageNameToTypingLocation, req.typeAcquisition, - req.unresolvedImports); + req.unresolvedImports, + this.typesRegistry); if (this.log.isEnabled()) { this.log.writeLine(`Finished typings discovery: ${JSON.stringify(discoverTypingsResult)}`); @@ -186,7 +134,7 @@ namespace ts.server.typingsInstaller { // install typings if (discoverTypingsResult.newTypingNames.length) { - this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames, timestampsFilePath); + this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames); } else { this.sendResponse(this.createSetTypings(req, discoverTypingsResult.cachedTypingPaths)); @@ -210,17 +158,16 @@ namespace ts.server.typingsInstaller { this.safeList = JsTyping.loadSafeList(this.installTypingHost, this.safeListPath); } - private processCacheLocation(cacheLocation: string, timestampsFilePath?: string) { + private processCacheLocation(cacheLocation: string) { if (this.log.isEnabled()) { this.log.writeLine(`Processing cache location '${cacheLocation}'`); } - if (this.knownCacheToTimestamps.has(cacheLocation)) { + if (this.knownCachesSet.has(cacheLocation)) { if (this.log.isEnabled()) { this.log.writeLine(`Cache location was already processed...`); } return; } - const typeDeclarationTimestamps = loadTypeDeclarationTimestampFile(timestampsFilePath || combinePaths(cacheLocation, timestampsFileName), this.installTypingHost, this.log); const packageJson = combinePaths(cacheLocation, "package.json"); const packageLockJson = combinePaths(cacheLocation, "package-lock.json"); if (this.log.isEnabled()) { @@ -258,20 +205,10 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Adding entry into typings cache: '${packageName}' => '${typingFile}'`); } - if (getProperty(typeDeclarationTimestamps, key) === undefined) { - // getModifiedTime is only undefined if we were to use the ChakraHost, but we never do in this scenario - // defaults to old behavior of never updating if we ever use a host without getModifiedTime in the future - const timestamp = this.installTypingHost.getModifiedTime === undefined ? Date.now() : this.installTypingHost.getModifiedTime(typingFile).getTime(); - typeDeclarationTimestamps[key] = timestamp; - if (this.log.isEnabled()) { - this.log.writeLine(`Adding entry into timestamp cache: '${key}' => '${timestamp}'`); - } - } const info = getProperty(npmLock.dependencies, key); const version = info && info.version; const semver = Semver.parse(version); - // timestamp guaranteed to not be undefined by above check - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: getProperty(typeDeclarationTimestamps, key), version: semver }; + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: semver }; this.packageNameToTypingLocation.set(packageName, newTyping); } } @@ -279,7 +216,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Finished processing cache location '${cacheLocation}'`); } - this.knownCacheToTimestamps.set(cacheLocation, typeDeclarationTimestamps); + this.knownCachesSet.set(cacheLocation, true); } private filterTypings(typingsToInstall: ReadonlyArray): ReadonlyArray { @@ -299,17 +236,12 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) this.log.writeLine(`Entry for package '${typing}' does not exist in local types registry - skipping...`); return false; } - if (this.packageNameToTypingLocation.get(typing) && isTypingUpToDate(this.packageNameToTypingLocation.get(typing), this.typesRegistry.get(typing))) { + if (this.packageNameToTypingLocation.get(typing) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typing), this.typesRegistry.get(typing))) { if (this.log.isEnabled()) this.log.writeLine(`'${typing}' already has an up-to-date typing - skipping...`); return false; } return true; }); - - function isTypingUpToDate(cachedTyping: JsTyping.CachedTyping, availableTypingVersions: MapLike) { - const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${ts.version}`)); - return !availableVersion.greaterThan(cachedTyping.version); - } } protected ensurePackageDirectoryExists(directory: string) { @@ -326,7 +258,7 @@ namespace ts.server.typingsInstaller { } } - private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[], timestampsFilePath: string) { + private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { if (this.log.isEnabled()) { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } @@ -369,9 +301,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Installed typings ${JSON.stringify(scopedTypings)}`); } - const typeDeclarationTimestamps = this.knownCacheToTimestamps.get(cachePath); const installedTypingFiles: string[] = []; - const typesPackageName = (packageName: string) => `@types/${packageName}`; for (const packageName of filteredTypings) { const typingFile = typingToFileName(cachePath, packageName, this.installTypingHost, this.log); if (!typingFile) { @@ -379,22 +309,15 @@ namespace ts.server.typingsInstaller { continue; } - const newTimestamp = Date.now(); const newVersion = Semver.parse(this.typesRegistry.get(packageName)[`ts${ts.versionMajorMinor}`]); - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, timestamp: newTimestamp, version: newVersion }; + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); - typeDeclarationTimestamps[typesPackageName(packageName)] = newTimestamp; installedTypingFiles.push(typingFile); } if (this.log.isEnabled()) { this.log.writeLine(`Installed typing files ${JSON.stringify(installedTypingFiles)}`); } - const updatedTypeDeclarationTimestamps = updateTypeDeclarationTimestampFile(timestampsFilePath, typeDeclarationTimestamps, this.installTypingHost, this.log); - const newFileContents: TypeDeclarationTimestampFile = { entries: updatedTypeDeclarationTimestamps }; - writeTypeDeclarationTimestampFile(timestampsFilePath, newFileContents, this.installTypingHost, this.log); - this.knownCacheToTimestamps.set(cachePath, updatedTypeDeclarationTimestamps); - this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); } finally { diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 75df1a7ea1b..3900a290bce 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -29,13 +29,13 @@ namespace ts.JsTyping { export interface CachedTyping { typingLocation: string; - timestamp: number; version: Semver; } - export function isTypingExpired(typing: JsTyping.CachedTyping | undefined) { - const msPerMonth = 1000 * 60 * 60 * 24 * 30; // ms/second * second/minute * minutes/hour * hours/day * days/month - return !typing || typing.timestamp < Date.now() - msPerMonth; + /* @internal */ + export function isTypingUpToDate(cachedTyping: JsTyping.CachedTyping, availableTypingVersions: MapLike) { + const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${ts.versionMajorMinor}`)); + return !availableVersion.greaterThan(cachedTyping.version); } /* @internal */ @@ -72,7 +72,7 @@ namespace ts.JsTyping { * @param fileNames are the file names that belong to the same project * @param projectRootPath is the path to the project root directory * @param safeListPath is the path used to retrieve the safe list - * @param packageNameToTypingLocation is the map of package names to their cached typing locations and time of caching and versions + * @param packageNameToTypingLocation is the map of package names to their cached typing locations and installed versions * @param typeAcquisition is used to customize the typing acquisition process * @param compilerOptions are used as a source for typing inference */ @@ -84,7 +84,8 @@ namespace ts.JsTyping { safeList: SafeList, packageNameToTypingLocation: ReadonlyMap, typeAcquisition: TypeAcquisition, - unresolvedImports: ReadonlyArray): + unresolvedImports: ReadonlyArray, + typesRegistry: ReadonlyMap>): { cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } { if (!typeAcquisition || !typeAcquisition.enable) { @@ -135,7 +136,7 @@ namespace ts.JsTyping { } // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach((typing, name) => { - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && !isTypingExpired(typing)) { + if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && isTypingUpToDate(typing, typesRegistry.get(name))) { inferredTypings.set(name, typing.typingLocation); } }); diff --git a/src/services/shims.ts b/src/services/shims.ts index d4bad1908e9..1b2f84035c0 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -28,10 +28,11 @@ namespace ts { fileNames: string[]; // The file names that belong to the same project. projectRootPath: string; // The path to the project root directory safeListPath: string; // The path used to retrieve the safe list - packageNameToTypingLocation: Map; // The map of package names to their cached typing locations + packageNameToTypingLocation: Map; // The map of package names to their cached typing locations and installed versions typeAcquisition: TypeAcquisition; // Used to customize the type acquisition process compilerOptions: CompilerOptions; // Used as a source for typing inference unresolvedImports: ReadonlyArray; // List of unresolved module ids from imports + typesRegistry: ReadonlyMap>; // The map of available typings in npm to maps of TS versions to their latest supported versions } export interface ScriptSnapshotShim { @@ -1171,7 +1172,8 @@ namespace ts { this.safeList, info.packageNameToTypingLocation, info.typeAcquisition, - info.unresolvedImports); + info.unresolvedImports, + info.typesRegistry); }); } } From 87c59450aa8ec37da091eb48ff6589872034d120 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 11 Jan 2018 11:29:08 -0800 Subject: [PATCH 13/32] Revert unnecessary harness changes --- src/harness/unittests/tsserverProjectSystem.ts | 6 ++---- src/harness/unittests/typingsInstaller.ts | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 2c5d4c59bab..b7536248d36 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -243,11 +243,9 @@ namespace ts.projectSystem { } } - export function createSession(host: TestServerHost, opts: Partial = {}) { + export function createSession(host: server.ServerHost, opts: Partial = {}) { if (opts.typingsInstaller === undefined) { - const globalTypingsCacheLocation = "/a/data"; - host.ensureFileOrFolder({ path: globalTypingsCacheLocation }); - opts.typingsInstaller = new TestTypingsInstaller(globalTypingsCacheLocation, /*throttleLimit*/ 5, host); + opts.typingsInstaller = new TestTypingsInstaller("/a/data", /*throttleLimit*/ 5, host); } if (opts.eventHandler !== undefined) { diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index cf3d82ca3d7..1e0a66f6d55 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -34,8 +34,7 @@ namespace ts.projectSystem { } class Installer extends TestTypingsInstaller { - constructor(host: TestServerHost, p?: InstallerParams, log?: TI.Log) { - host.ensureFileOrFolder({ path: (p && p.globalTypingsCacheLocation) || "/a/data" }); + constructor(host: server.ServerHost, p?: InstallerParams, log?: TI.Log) { super( (p && p.globalTypingsCacheLocation) || "/a/data", (p && p.throttleLimit) || 5, From 2a0d5d173dbe46a33bb9c6ec32f9aaa0de1e45fa Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 11 Jan 2018 13:07:47 -0800 Subject: [PATCH 14/32] Fix tests --- src/harness/unittests/tsserverProjectSystem.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index b7536248d36..279bec7db04 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -245,7 +245,7 @@ namespace ts.projectSystem { export function createSession(host: server.ServerHost, opts: Partial = {}) { if (opts.typingsInstaller === undefined) { - opts.typingsInstaller = new TestTypingsInstaller("/a/data", /*throttleLimit*/ 5, host); + opts.typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/ 5, host); } if (opts.eventHandler !== undefined) { @@ -6532,7 +6532,7 @@ namespace ts.projectSystem { const files = [file, packageJsonInCurrentDirectory, packageJsonOfPkgcurrentdirectory, indexOfPkgcurrentdirectory, typingsCachePackageJson]; const host = createServerHost(files, { currentDirectory }); - const typesRegistry = createMap(); + const typesRegistry = createMap>(); typesRegistry.set("pkgcurrentdirectory", void 0); const typingsInstaller = new TestTypingsInstaller(typingsCache, /*throttleLimit*/ 5, host, typesRegistry); From aff02e879cde1e614526fa044f1f09f456542765 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Thu, 11 Jan 2018 13:20:45 -0800 Subject: [PATCH 15/32] Move createTypesRegistry so more accessible --- .../unittests/tsserverProjectSystem.ts | 31 +++++++++++++++++-- src/harness/unittests/typingsInstaller.ts | 19 ------------ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 279bec7db04..90c38186828 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -126,6 +126,25 @@ namespace ts.projectSystem { return JSON.stringify({ dependencies }); } + export function createTypesRegistry(...list: string[]): Map> { + const versionMap = { + "latest": "1.3.0", + "ts2.0": "1.0.0", + "ts2.1": "1.0.0", + "ts2.2": "1.2.0", + "ts2.3": "1.3.0", + "ts2.4": "1.3.0", + "ts2.5": "1.3.0", + "ts2.6": "1.3.0", + "ts2.7": "1.3.0" + }; + const map = createMap>(); + for (const l of list) { + map.set(l, versionMap); + } + return map; + } + export function toExternalFile(fileName: string): protocol.ExternalFile { return { fileName }; } @@ -6528,12 +6547,18 @@ namespace ts.projectSystem { }, }) }; + const typingsCachePackageLockJson: FileOrFolder = { + path: `${typingsCache}/package-lock.json`, + content: JSON.stringify({ + dependencies: { + }, + }) + }; - const files = [file, packageJsonInCurrentDirectory, packageJsonOfPkgcurrentdirectory, indexOfPkgcurrentdirectory, typingsCachePackageJson]; + const files = [file, packageJsonInCurrentDirectory, packageJsonOfPkgcurrentdirectory, indexOfPkgcurrentdirectory, typingsCachePackageJson, typingsCachePackageLockJson]; const host = createServerHost(files, { currentDirectory }); - const typesRegistry = createMap>(); - typesRegistry.set("pkgcurrentdirectory", void 0); + const typesRegistry = createTypesRegistry("pkgcurrentdirectory"); const typingsInstaller = new TestTypingsInstaller(typingsCache, /*throttleLimit*/ 5, host, typesRegistry); const projectService = createProjectService(host, { typingsInstaller }); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 1e0a66f6d55..33f3544bde8 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -14,25 +14,6 @@ namespace ts.projectSystem { typesRegistry?: Map>; } - function createTypesRegistry(...list: string[]): Map> { - const versionMap = { - "latest": "1.3.0", - "ts2.0": "1.0.0", - "ts2.1": "1.0.0", - "ts2.2": "1.2.0", - "ts2.3": "1.3.0", - "ts2.4": "1.3.0", - "ts2.5": "1.3.0", - "ts2.6": "1.3.0", - "ts2.7": "1.3.0" - }; - const map = createMap>(); - for (const l of list) { - map.set(l, versionMap); - } - return map; - } - class Installer extends TestTypingsInstaller { constructor(host: server.ServerHost, p?: InstallerParams, log?: TI.Log) { super( From d34b86573c36721d13e7ff76d221ed75b710497c Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Fri, 19 Jan 2018 13:13:51 -0800 Subject: [PATCH 16/32] Respond to CR --- src/server/typingsInstaller/typingsInstaller.ts | 4 +++- src/services/semver.ts | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 18890d8af05..fa31384a453 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -309,7 +309,9 @@ namespace ts.server.typingsInstaller { continue; } - const newVersion = Semver.parse(this.typesRegistry.get(packageName)[`ts${ts.versionMajorMinor}`]); + // packageName is guaranteed to exist in typesRegistry by filterTypings + const distTags = this.typesRegistry.get(packageName); + const newVersion = Semver.parse(distTags[`ts${ts.versionMajorMinor}`] || distTags["latest"]); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); installedTypingFiles.push(typingFile); diff --git a/src/services/semver.ts b/src/services/semver.ts index 1f2d8e3de45..b16d6041529 100644 --- a/src/services/semver.ts +++ b/src/services/semver.ts @@ -1,6 +1,6 @@ /* @internal */ namespace ts { - function intOfString(str: string): number { + function stringToInt(str: string): number { const n = parseInt(str, 10); if (isNaN(n)) { throw new Error(`Error in parseInt(${JSON.stringify(str)})`); @@ -28,10 +28,10 @@ namespace ts { // "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes." const rgx = isPrerelease ? /^(\d+)\.(\d+)\.0-next.(\d+)$/ : /^(\d+)\.(\d+)\.(\d+)$/; const match = rgx.exec(semver); - return match ? new Semver(intOfString(match[1]), intOfString(match[2]), intOfString(match[3]), isPrerelease) : undefined; + return match ? new Semver(stringToInt(match[1]), stringToInt(match[2]), stringToInt(match[3]), isPrerelease) : undefined; } - constructor( + private constructor( readonly major: number, readonly minor: number, readonly patch: number, /** * If true, this is `major.minor.0-next.patch`. @@ -49,7 +49,9 @@ namespace ts { greaterThan(sem: Semver): boolean { return this.major > sem.major || this.major === sem.major - && (this.minor > sem.minor || this.minor === sem.minor && this.patch > sem.patch); + && (this.minor > sem.minor || this.minor === sem.minor + && (!this.isPrerelease && sem.isPrerelease || this.isPrerelease === sem.isPrerelease + && this.patch > sem.patch)); } } } \ No newline at end of file From 7397fb11c4cbc651a2d0be5180a003fecd46716e Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Fri, 19 Jan 2018 14:10:06 -0800 Subject: [PATCH 17/32] Fix lint and test errors and add tests --- src/harness/unittests/typingsInstaller.ts | 64 ++++++++++++++++++- .../typingsInstaller/typingsInstaller.ts | 4 +- src/services/semver.ts | 2 +- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 33f3544bde8..b5265c5e5f2 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1300,7 +1300,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f, node]); - const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: new Semver(1, 3, 0, /*isPrerelease*/ false) } }); + const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: Semver.parse("1.3.0") } }); const registry = createTypesRegistry("node"); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"], registry); @@ -1358,8 +1358,8 @@ namespace ts.projectSystem { }; const host = createServerHost([app]); const cache = createMapFromTemplate({ - node: { typingLocation: node.path, version: new Semver(1, 3, 0, /*isPrerelease*/ false) }, - commander: { typingLocation: commander.path, version: new Semver(1, 0, 0, /*isPrerelease*/ false) } + node: { typingLocation: node.path, version: Semver.parse("1.3.0") }, + commander: { typingLocation: commander.path, version: Semver.parse("1.0.0") } }); const registry = createTypesRegistry("node", "commander"); const logger = trackingLogger(); @@ -1371,6 +1371,64 @@ namespace ts.projectSystem { assert.deepEqual(result.cachedTypingPaths, [node.path]); assert.deepEqual(result.newTypingNames, ["commander"]); }); + + it("should install expired typings with prerelease version of tsserver", () => { + const app = { + path: "/a/app.js", + content: "" + }; + const cachePath = "/a/cache/"; + const node = { + path: cachePath + "node_modules/@types/node/index.d.ts", + content: "export let y: number" + }; + const host = createServerHost([app]); + const cache = createMapFromTemplate({ + node: { typingLocation: node.path, version: Semver.parse("1.0.0") } + }); + const registry = createTypesRegistry("node"); + registry.delete(`ts${ts.versionMajorMinor}`); + const logger = trackingLogger(); + const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, ["http"], registry); + assert.deepEqual(logger.finish(), [ + 'Inferred typings from unresolved imports: ["node"]', + 'Result: {"cachedTypingPaths":[],"newTypingNames":["node"],"filesToWatch":["/a/bower_components","/a/node_modules"]}', + ]); + assert.deepEqual(result.cachedTypingPaths, []); + assert.deepEqual(result.newTypingNames, ["node"]); + }); + + + it("prerelease typings are properly handled", () => { + const app = { + path: "/a/app.js", + content: "" + }; + const cachePath = "/a/cache/"; + const commander = { + path: cachePath + "node_modules/@types/commander/index.d.ts", + content: "export let x: number" + }; + const node = { + path: cachePath + "node_modules/@types/node/index.d.ts", + content: "export let y: number" + }; + const host = createServerHost([app]); + const cache = createMapFromTemplate({ + node: { typingLocation: node.path, version: Semver.parse("1.3.0-next.0") }, + commander: { typingLocation: commander.path, version: Semver.parse("1.3.0-next.0") } + }); + const registry = createTypesRegistry("node", "commander"); + registry.get("node")[`ts${ts.versionMajorMinor}`] = "1.3.0-next.1"; + const logger = trackingLogger(); + const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, ["http", "commander"], registry); + assert.deepEqual(logger.finish(), [ + 'Inferred typings from unresolved imports: ["node","commander"]', + 'Result: {"cachedTypingPaths":[],"newTypingNames":["node","commander"],"filesToWatch":["/a/bower_components","/a/node_modules"]}', + ]); + assert.deepEqual(result.cachedTypingPaths, []); + assert.deepEqual(result.newTypingNames, ["node", "commander"]); + }); }); describe("telemetry events", () => { diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index fa31384a453..09c0e76e8d0 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -311,7 +311,7 @@ namespace ts.server.typingsInstaller { // packageName is guaranteed to exist in typesRegistry by filterTypings const distTags = this.typesRegistry.get(packageName); - const newVersion = Semver.parse(distTags[`ts${ts.versionMajorMinor}`] || distTags["latest"]); + const newVersion = Semver.parse(distTags[`ts${ts.versionMajorMinor}`] || distTags[latestDistTag]); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); installedTypingFiles.push(typingFile); @@ -407,4 +407,6 @@ namespace ts.server.typingsInstaller { export function typingsName(packageName: string): string { return `@types/${packageName}@ts${versionMajorMinor}`; } + + const latestDistTag = "latest"; } \ No newline at end of file diff --git a/src/services/semver.ts b/src/services/semver.ts index b16d6041529..3415ff9176f 100644 --- a/src/services/semver.ts +++ b/src/services/semver.ts @@ -23,7 +23,7 @@ namespace ts { } // This must parse the output of `versionString`. - static tryParse(semver: string, isPrerelease: boolean): Semver | undefined { + private static tryParse(semver: string, isPrerelease: boolean): Semver | undefined { // Per the semver spec : // "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes." const rgx = isPrerelease ? /^(\d+)\.(\d+)\.0-next.(\d+)$/ : /^(\d+)\.(\d+)\.(\d+)$/; From f8eac24f08fa1f1ba84b7f25795362d41a81377c Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Fri, 19 Jan 2018 17:09:12 -0800 Subject: [PATCH 18/32] Make regexes instantiate only once --- src/services/semver.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/services/semver.ts b/src/services/semver.ts index 3415ff9176f..1c58da8c8f7 100644 --- a/src/services/semver.ts +++ b/src/services/semver.ts @@ -8,9 +8,13 @@ namespace ts { return n; } + const isPrereleaseRegex = /^(.*)-next.\d+/; + const prereleaseSemverRegex = /^(\d+)\.(\d+)\.0-next.(\d+)$/; + const semverRegex = /^(\d+)\.(\d+)\.(\d+)$/; + export class Semver { static parse(semver: string): Semver { - const isPrerelease = /^(.*)-next.\d+/.test(semver); + const isPrerelease = isPrereleaseRegex.test(semver); const result = Semver.tryParse(semver, isPrerelease); if (!result) { throw new Error(`Unexpected semver: ${semver} (isPrerelease: ${isPrerelease})`); @@ -26,7 +30,7 @@ namespace ts { private static tryParse(semver: string, isPrerelease: boolean): Semver | undefined { // Per the semver spec : // "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes." - const rgx = isPrerelease ? /^(\d+)\.(\d+)\.0-next.(\d+)$/ : /^(\d+)\.(\d+)\.(\d+)$/; + const rgx = isPrerelease ? prereleaseSemverRegex : semverRegex; const match = rgx.exec(semver); return match ? new Semver(stringToInt(match[1]), stringToInt(match[2]), stringToInt(match[3]), isPrerelease) : undefined; } From 1d5e5e6205dd3bb5aeaac10ca2b627838846c39d Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Wed, 24 Jan 2018 13:56:30 -0800 Subject: [PATCH 19/32] Handle missing ts versions in registry --- src/services/jsTyping.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 3900a290bce..bd6c2e5cb9f 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -34,7 +34,7 @@ namespace ts.JsTyping { /* @internal */ export function isTypingUpToDate(cachedTyping: JsTyping.CachedTyping, availableTypingVersions: MapLike) { - const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${ts.versionMajorMinor}`)); + const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${ts.versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")); return !availableVersion.greaterThan(cachedTyping.version); } From 8d6e48a2ec06c0c793323625a8c399a2b2cf13ba Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 8 Feb 2018 15:28:59 -0800 Subject: [PATCH 20/32] Change the meaning of useNonAdjustedStartPosition Old: getFullStart New: getStart Impact: only used in tests Reason: symmetry with useNonAdjustedEndPosition - both now effectively mean "exclude trivia from range" --- src/services/textChanges.ts | 4 +++- tests/baselines/reference/textChanges/deleteNode2.js | 6 +++++- tests/baselines/reference/textChanges/deleteNode4.js | 6 +++++- tests/baselines/reference/textChanges/deleteNodeRange2.js | 4 +++- tests/baselines/reference/textChanges/deleteNodeRange4.js | 4 +++- tests/baselines/reference/textChanges/replaceNode2.js | 4 +++- tests/baselines/reference/textChanges/replaceNode4.js | 4 +++- tests/baselines/reference/textChanges/replaceNode5.js | 2 ++ tests/baselines/reference/textChanges/replaceNodeRange2.js | 4 +++- tests/baselines/reference/textChanges/replaceNodeRange4.js | 4 +++- 10 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 83b434aac7d..fc61ae36195 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -28,9 +28,11 @@ namespace ts.textChanges { } export interface ConfigurableStart { + /** True to use getStart() (NB, not getFullStart()) without adjustment. */ useNonAdjustedStartPosition?: boolean; } export interface ConfigurableEnd { + /** True to use getEnd() without adjustment. */ useNonAdjustedEndPosition?: boolean; } @@ -132,7 +134,7 @@ namespace ts.textChanges { export function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStart, position: Position) { if (options.useNonAdjustedStartPosition) { - return node.getFullStart(); + return node.getStart(); } const fullStart = node.getFullStart(); const start = node.getStart(sourceFile); diff --git a/tests/baselines/reference/textChanges/deleteNode2.js b/tests/baselines/reference/textChanges/deleteNode2.js index 828a9b5b8fa..654c4929f15 100644 --- a/tests/baselines/reference/textChanges/deleteNode2.js +++ b/tests/baselines/reference/textChanges/deleteNode2.js @@ -9,4 +9,8 @@ var z = 3; // comment 4 ===MODIFIED=== -var x = 1;var z = 3; // comment 4 +var x = 1; // some comment - 1 +/** + * comment 2 + */ +var z = 3; // comment 4 diff --git a/tests/baselines/reference/textChanges/deleteNode4.js b/tests/baselines/reference/textChanges/deleteNode4.js index b6edb25bc5c..d6c35e5d2e1 100644 --- a/tests/baselines/reference/textChanges/deleteNode4.js +++ b/tests/baselines/reference/textChanges/deleteNode4.js @@ -9,5 +9,9 @@ var z = 3; // comment 4 ===MODIFIED=== -var x = 1; // comment 3 +var x = 1; // some comment - 1 +/** + * comment 2 + */ + // comment 3 var z = 3; // comment 4 diff --git a/tests/baselines/reference/textChanges/deleteNodeRange2.js b/tests/baselines/reference/textChanges/deleteNodeRange2.js index aacea6ff5ee..08274885af4 100644 --- a/tests/baselines/reference/textChanges/deleteNodeRange2.js +++ b/tests/baselines/reference/textChanges/deleteNodeRange2.js @@ -11,5 +11,7 @@ var a = 4; // comment 7 ===MODIFIED=== // comment 1 -var x = 1;// comment 6 +var x = 1; // comment 2 +// comment 3 +// comment 6 var a = 4; // comment 7 diff --git a/tests/baselines/reference/textChanges/deleteNodeRange4.js b/tests/baselines/reference/textChanges/deleteNodeRange4.js index 3e9ad960b13..5314c59c9e4 100644 --- a/tests/baselines/reference/textChanges/deleteNodeRange4.js +++ b/tests/baselines/reference/textChanges/deleteNodeRange4.js @@ -11,6 +11,8 @@ var a = 4; // comment 7 ===MODIFIED=== // comment 1 -var x = 1; // comment 5 +var x = 1; // comment 2 +// comment 3 + // comment 5 // comment 6 var a = 4; // comment 7 diff --git a/tests/baselines/reference/textChanges/replaceNode2.js b/tests/baselines/reference/textChanges/replaceNode2.js index 66a17f7c910..f474aaa327b 100644 --- a/tests/baselines/reference/textChanges/replaceNode2.js +++ b/tests/baselines/reference/textChanges/replaceNode2.js @@ -10,7 +10,9 @@ var a = 4; // comment 7 ===MODIFIED=== // comment 1 -var x = 1; +var x = 1; // comment 2 +// comment 3 + public class class1 implements interface1 { property1: boolean; diff --git a/tests/baselines/reference/textChanges/replaceNode4.js b/tests/baselines/reference/textChanges/replaceNode4.js index e5bbf0e306d..b5a998a88cd 100644 --- a/tests/baselines/reference/textChanges/replaceNode4.js +++ b/tests/baselines/reference/textChanges/replaceNode4.js @@ -10,7 +10,9 @@ var a = 4; // comment 7 ===MODIFIED=== // comment 1 -var x = 1;public class class1 implements interface1 +var x = 1; // comment 2 +// comment 3 +public class class1 implements interface1 { property1: boolean; } // comment 4 diff --git a/tests/baselines/reference/textChanges/replaceNode5.js b/tests/baselines/reference/textChanges/replaceNode5.js index ad3ec0ab0ea..9fc6d7777c9 100644 --- a/tests/baselines/reference/textChanges/replaceNode5.js +++ b/tests/baselines/reference/textChanges/replaceNode5.js @@ -8,6 +8,8 @@ var z = 3; // comment 5 // comment 6 var a = 4; // comment 7 ===MODIFIED=== + +// comment 1 public class class1 implements interface1 { property1: boolean; diff --git a/tests/baselines/reference/textChanges/replaceNodeRange2.js b/tests/baselines/reference/textChanges/replaceNodeRange2.js index e8f9506d608..ebd26644740 100644 --- a/tests/baselines/reference/textChanges/replaceNodeRange2.js +++ b/tests/baselines/reference/textChanges/replaceNodeRange2.js @@ -10,7 +10,9 @@ var a = 4; // comment 7 ===MODIFIED=== // comment 1 -var x = 1; +var x = 1; // comment 2 +// comment 3 + public class class1 implements interface1 { property1: boolean; diff --git a/tests/baselines/reference/textChanges/replaceNodeRange4.js b/tests/baselines/reference/textChanges/replaceNodeRange4.js index ad50a1f01fc..b21468dd06d 100644 --- a/tests/baselines/reference/textChanges/replaceNodeRange4.js +++ b/tests/baselines/reference/textChanges/replaceNodeRange4.js @@ -10,7 +10,9 @@ var a = 4; // comment 7 ===MODIFIED=== // comment 1 -var x = 1;public class class1 implements interface1 +var x = 1; // comment 2 +// comment 3 +public class class1 implements interface1 { property1: boolean; } // comment 5 From 80b2c58c5198e70a24bc7c8fbe46f79498e2221b Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 8 Feb 2018 13:39:03 -0800 Subject: [PATCH 21/32] Eliminate replaceWithSingle in favor of replaceRange --- src/services/textChanges.ts | 39 +++++++++++++------------------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index fc61ae36195..f2109b34751 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -288,26 +288,15 @@ namespace ts.textChanges { } public replaceNode(sourceFile: SourceFile, oldNode: Node, newNode: Node, options: ChangeNodeOptions = {}) { - const startPosition = getAdjustedStartPosition(sourceFile, oldNode, options, Position.Start); - const endPosition = getAdjustedEndPosition(sourceFile, oldNode, options); - return this.replaceWithSingle(sourceFile, startPosition, endPosition, newNode, options); + const pos = getAdjustedStartPosition(sourceFile, oldNode, options, Position.Start); + const end = getAdjustedEndPosition(sourceFile, oldNode, options); + return this.replaceRange(sourceFile, { pos, end }, newNode, options); } public replaceNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, newNode: Node, options: ChangeNodeOptions = {}) { - const startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.Start); - const endPosition = getAdjustedEndPosition(sourceFile, endNode, options); - return this.replaceWithSingle(sourceFile, startPosition, endPosition, newNode, options); - } - - private replaceWithSingle(sourceFile: SourceFile, startPosition: number, endPosition: number, newNode: Node, options: ChangeNodeOptions): this { - this.changes.push({ - kind: ChangeKind.ReplaceWithSingleNode, - sourceFile, - options, - node: newNode, - range: { pos: startPosition, end: endPosition } - }); - return this; + const pos = getAdjustedStartPosition(sourceFile, startNode, options, Position.Start); + const end = getAdjustedEndPosition(sourceFile, endNode, options); + return this.replaceRange(sourceFile, { pos, end }, newNode, options); } private replaceWithMultiple(sourceFile: SourceFile, startPosition: number, endPosition: number, newNodes: ReadonlyArray, options: ChangeMultipleNodesOptions): this { @@ -343,18 +332,18 @@ namespace ts.textChanges { } public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false) { - const startPosition = getAdjustedStartPosition(sourceFile, before, {}, Position.Start); - return this.replaceWithSingle(sourceFile, startPosition, startPosition, newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); + const pos = getAdjustedStartPosition(sourceFile, before, {}, Position.Start); + return this.replaceRange(sourceFile, { pos, end: pos }, newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); } public insertModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void { const pos = before.getStart(sourceFile); - this.replaceWithSingle(sourceFile, pos, pos, createToken(modifier), { suffix: " " }); + this.replaceRange(sourceFile, { pos, end: pos }, createToken(modifier), { suffix: " " }); } public changeIdentifierToPropertyAccess(sourceFile: SourceFile, prefix: string, node: Identifier): void { - const startPosition = getAdjustedStartPosition(sourceFile, node, {}, Position.Start); - this.replaceWithSingle(sourceFile, startPosition, startPosition, createPropertyAccess(createIdentifier(prefix), ""), {}); + const pos = getAdjustedStartPosition(sourceFile, node, {}, Position.Start); + this.replaceRange(sourceFile, { pos, end: pos }, createPropertyAccess(createIdentifier(prefix), ""), {}); } private getOptionsForInsertNodeBefore(before: Node, doubleNewlines: boolean): ChangeNodeOptions { @@ -392,8 +381,8 @@ namespace ts.textChanges { } public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void { - const startPosition = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); - this.replaceWithSingle(sourceFile, startPosition, startPosition, newNode, { + const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); + this.replaceRange(sourceFile, { pos, end: pos }, newNode, { prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter }); @@ -435,7 +424,7 @@ namespace ts.textChanges { } } const endPosition = getAdjustedEndPosition(sourceFile, after, {}); - return this.replaceWithSingle(sourceFile, endPosition, endPosition, newNode, this.getInsertNodeAfterOptions(after)); + return this.replaceRange(sourceFile, { pos: endPosition, end: endPosition }, newNode, this.getInsertNodeAfterOptions(after)); } private getInsertNodeAfterOptions(node: Node): InsertNodeOptions { From f77cefee88be6fe0ddd8cc9b2aff089736949c91 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 8 Feb 2018 15:05:36 -0800 Subject: [PATCH 22/32] Introduce *WithNodes paralleling textChanges.Replace* 1) Take options 2) Return `this` 3) Use adjusted positions --- src/services/refactors/extractSymbol.ts | 2 +- src/services/textChanges.ts | 32 +++++++++++++++---------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 74a944077ec..20895d7992a 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -968,7 +968,7 @@ namespace ts.refactor.extractSymbol { } if (isReadonlyArray(range.range)) { - changeTracker.replaceNodesWithNodes(context.file, range.range, newNodes); + changeTracker.replaceNodeRangeWithNodes(context.file, first(range.range), last(range.range), newNodes); } else { changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes); diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index f2109b34751..98e37f7656d 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -282,7 +282,7 @@ namespace ts.textChanges { return this; } - public replaceRange(sourceFile: SourceFile, range: TextRange, newNode: Node, options: InsertNodeOptions = {}) { + public replaceRange(sourceFile: SourceFile, range: TextRange, newNode: Node, options: ChangeNodeOptions = {}) { this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile, range, options, node: newNode }); return this; } @@ -299,23 +299,29 @@ namespace ts.textChanges { return this.replaceRange(sourceFile, { pos, end }, newNode, options); } - private replaceWithMultiple(sourceFile: SourceFile, startPosition: number, endPosition: number, newNodes: ReadonlyArray, options: ChangeMultipleNodesOptions): this { - this.changes.push({ - kind: ChangeKind.ReplaceWithMultipleNodes, - sourceFile, - options, - nodes: newNodes, - range: { pos: startPosition, end: endPosition } - }); + private getDefaultChangeMultipleNodesOptions(): ChangeMultipleNodesOptions { + return { + nodeSeparator: this.newLineCharacter, + useNonAdjustedStartPosition: true, + useNonAdjustedEndPosition: true, + }; + } + + public replaceRangeWithNodes(sourceFile: SourceFile, range: TextRange, newNodes: ReadonlyArray, options: ChangeMultipleNodesOptions = this.getDefaultChangeMultipleNodesOptions()) { + this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile, range, options, nodes: newNodes }); return this; } - public replaceNodeWithNodes(sourceFile: SourceFile, oldNode: Node, newNodes: ReadonlyArray): void { - this.replaceWithMultiple(sourceFile, oldNode.getStart(sourceFile), oldNode.getEnd(), newNodes, { nodeSeparator: this.newLineCharacter }); + public replaceNodeWithNodes(sourceFile: SourceFile, oldNode: Node, newNodes: ReadonlyArray, options: ChangeMultipleNodesOptions = this.getDefaultChangeMultipleNodesOptions()) { + const pos = getAdjustedStartPosition(sourceFile, oldNode, options, Position.Start); + const end = getAdjustedEndPosition(sourceFile, oldNode, options); + return this.replaceRangeWithNodes(sourceFile, { pos, end }, newNodes, options); } - public replaceNodesWithNodes(sourceFile: SourceFile, oldNodes: ReadonlyArray, newNodes: ReadonlyArray): void { - this.replaceWithMultiple(sourceFile, first(oldNodes).getStart(sourceFile), last(oldNodes).getEnd(), newNodes, { nodeSeparator: this.newLineCharacter }); + public replaceNodeRangeWithNodes(sourceFile: SourceFile, startNode: Node, endNode: Node, newNodes: ReadonlyArray, options: ChangeMultipleNodesOptions = this.getDefaultChangeMultipleNodesOptions()) { + const pos = getAdjustedStartPosition(sourceFile, startNode, options, Position.Start); + const end = getAdjustedEndPosition(sourceFile, endNode, options); + return this.replaceRangeWithNodes(sourceFile, { pos, end }, newNodes, options); } private insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}) { From 1b620886a9107772c58a1faece22d589460feb8b Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 9 Feb 2018 10:28:31 -0800 Subject: [PATCH 23/32] Assert getExportEqualsLocalSymbol returns a defined result (#21831) --- src/services/importTracker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 91544e209cb..02d0979ca1e 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -577,17 +577,17 @@ namespace ts.FindAllReferences { function getExportEqualsLocalSymbol(importedSymbol: Symbol, checker: TypeChecker): Symbol { if (importedSymbol.flags & SymbolFlags.Alias) { - return checker.getImmediateAliasedSymbol(importedSymbol); + return Debug.assertDefined(checker.getImmediateAliasedSymbol(importedSymbol)); } const decl = importedSymbol.valueDeclaration; if (isExportAssignment(decl)) { // `export = class {}` - return decl.expression.symbol; + return Debug.assertDefined(decl.expression.symbol); } else if (isBinaryExpression(decl)) { // `module.exports = class {}` - return decl.right.symbol; + return Debug.assertDefined(decl.right.symbol); } - Debug.fail(); + return Debug.fail(); } // If a reference is a class expression, the exported node would be its parent. From 4c89a813bf7eb26f3cc259ef28067e19b184e3b1 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Fri, 9 Feb 2018 10:36:49 -0800 Subject: [PATCH 24/32] Handle case where package.json and package-lock.json don't agree --- src/server/typingsInstaller/typingsInstaller.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 09c0e76e8d0..465f281006e 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -182,6 +182,10 @@ namespace ts.server.typingsInstaller { } if (npmConfig.devDependencies && npmLock.dependencies) { for (const key in npmConfig.devDependencies) { + if (!hasProperty(npmLock.dependencies, key)) { + // if package in package.json but not package-lock.json, skip adding to cache so it is reinstalled on next use + continue; + } // key is @types/ const packageName = getBaseFileName(key); if (!packageName) { From aa1ebda6a6978c898bf37a5d0c9bdfced90e1cce Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 9 Feb 2018 13:48:40 -0800 Subject: [PATCH 25/32] Fix bug: handle missing symbol.parent for non-accessible symbol (#21834) --- src/services/completions.ts | 2 +- .../completionsRecommended_nonAccessibleSymbol.ts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/completionsRecommended_nonAccessibleSymbol.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 2add52cc3dd..c6d5f015279 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -712,7 +712,7 @@ namespace ts.Completions { function getFirstSymbolInChain(symbol: Symbol, enclosingDeclaration: Node, checker: TypeChecker): Symbol | undefined { const chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ SymbolFlags.All, /*useOnlyExternalAliasing*/ false); if (chain) return first(chain); - return isModuleSymbol(symbol.parent) ? symbol : symbol.parent && getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker); + return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker)); } function isModuleSymbol(symbol: Symbol): boolean { diff --git a/tests/cases/fourslash/completionsRecommended_nonAccessibleSymbol.ts b/tests/cases/fourslash/completionsRecommended_nonAccessibleSymbol.ts new file mode 100644 index 00000000000..0f27e824d2b --- /dev/null +++ b/tests/cases/fourslash/completionsRecommended_nonAccessibleSymbol.ts @@ -0,0 +1,10 @@ +/// + +////function f() { +//// class C {} +//// return (c: C) => void; +////} +////f()(new /**/); + +goTo.marker(""); +verify.not.completionListContains("C"); // Not accessible From 31ec5e7390a5d711e5cd9fe85e3beca2dd9b3d8c Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 9 Feb 2018 13:56:04 -0800 Subject: [PATCH 26/32] findAllReferences: Don't fail on broken re-export (#21841) --- src/services/findAllReferences.ts | 5 +++-- tests/cases/fourslash/findAllRefsReExport_broken.ts | 6 ++++++ tests/cases/fourslash/findAllRefsReExport_broken2.ts | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/findAllRefsReExport_broken.ts create mode 100644 tests/cases/fourslash/findAllRefsReExport_broken2.ts diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 8b9937394f1..ad243d59d89 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -914,7 +914,8 @@ namespace ts.FindAllReferences.Core { // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`. if (search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName) { - searchForImportedSymbol(state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier), state); + const imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier); + if (imported) searchForImportedSymbol(imported, state); } function addRef() { @@ -923,7 +924,7 @@ namespace ts.FindAllReferences.Core { } function getLocalSymbolForExportSpecifier(referenceLocation: Identifier, referenceSymbol: Symbol, exportSpecifier: ExportSpecifier, checker: TypeChecker): Symbol { - return isExportSpecifierAlias(referenceLocation, exportSpecifier) ? checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) : referenceSymbol; + return isExportSpecifierAlias(referenceLocation, exportSpecifier) && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) || referenceSymbol; } function isExportSpecifierAlias(referenceLocation: Identifier, exportSpecifier: ExportSpecifier): boolean { diff --git a/tests/cases/fourslash/findAllRefsReExport_broken.ts b/tests/cases/fourslash/findAllRefsReExport_broken.ts new file mode 100644 index 00000000000..7c42d9e2b6c --- /dev/null +++ b/tests/cases/fourslash/findAllRefsReExport_broken.ts @@ -0,0 +1,6 @@ +/// + +// @Filename: /a.ts +////export { [|{| "isWriteAccess": true, "isDefinition": true |}x|] }; + +verify.singleReferenceGroup("import x"); diff --git a/tests/cases/fourslash/findAllRefsReExport_broken2.ts b/tests/cases/fourslash/findAllRefsReExport_broken2.ts new file mode 100644 index 00000000000..4f8a3ea5f45 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsReExport_broken2.ts @@ -0,0 +1,6 @@ +/// + +// @Filename: /a.ts +////export { [|{| "isWriteAccess": true, "isDefinition": true |}x|] } from "nonsense"; + +verify.singleReferenceGroup("import x"); From 171b68c9e75ec9f1f8055492e7168ab10ef0a96b Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 9 Feb 2018 14:08:56 -0800 Subject: [PATCH 27/32] Add assertions for bad symbol declaration (#21837) * Add assertions for bad symbol declaration * Fix lint --- src/compiler/checker.ts | 4 ++-- src/compiler/core.ts | 21 ++++++++++++++++++++- src/services/findAllReferences.ts | 12 +++++++++--- src/services/importTracker.ts | 19 +------------------ 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0612c4d4307..7da5d747391 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4406,7 +4406,7 @@ namespace ts { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); } else { - Debug.fail("Unhandled declaration kind! " + (ts as any).SyntaxKind[declaration.kind]); + Debug.fail("Unhandled declaration kind! " + Debug.showSyntaxKind(declaration)); } if (!popTypeResolution()) { @@ -20682,7 +20682,7 @@ namespace ts { case SyntaxKind.ImportSpecifier: // https://github.com/Microsoft/TypeScript/pull/7591 return DeclarationSpaces.ExportValue; default: - Debug.fail((ts as any).SyntaxKind[d.kind]); + Debug.fail(Debug.showSyntaxKind(d)); } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index fe8e63676d7..8479cf94180 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1466,7 +1466,7 @@ namespace ts { if (value !== undefined && test(value)) return value; if (value && typeof (value as any).kind === "number") { - Debug.fail(`Invalid cast. The supplied ${(ts as any).SyntaxKind[(value as any).kind]} did not pass the test '${Debug.getFunctionName(test)}'.`); + Debug.fail(`Invalid cast. The supplied ${Debug.showSyntaxKind(value as any as Node)} did not pass the test '${Debug.getFunctionName(test)}'.`); } else { Debug.fail(`Invalid cast. The supplied value did not pass the test '${Debug.getFunctionName(test)}'.`); @@ -2925,6 +2925,25 @@ namespace ts { return match ? match[1] : ""; } } + + export function showSymbol(symbol: Symbol): string { + return `{ flags: ${showFlags(symbol.flags, (ts as any).SymbolFlags)}; declarations: ${map(symbol.declarations, showSyntaxKind)} }`; + } + + function showFlags(flags: number, flagsEnum: { [flag: number]: string }): string { + const out = []; + for (let pow = 0; pow <= 30; pow++) { + const n = 1 << pow; + if (flags & n) { + out.push(flagsEnum[n]); + } + } + return out.join("|"); + } + + export function showSyntaxKind(node: Node): string { + return (ts as any).SyntaxKind[node.kind]; + } } /** Remove an item from an array, moving everything to its right one space left. */ diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index ad243d59d89..acc3e6ac4cb 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -416,10 +416,16 @@ namespace ts.FindAllReferences.Core { } // If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references. - return firstDefined(symbol.declarations, decl => - isTypeLiteralNode(decl.parent) && isUnionTypeNode(decl.parent.parent) + return firstDefined(symbol.declarations, decl => { + if (!decl.parent) { + // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here. + Debug.assert(decl.kind === SyntaxKind.SourceFile); + Debug.fail(`Unexpected symbol at ${Debug.showSyntaxKind(node)}: ${Debug.showSymbol(symbol)}`); + } + return isTypeLiteralNode(decl.parent) && isUnionTypeNode(decl.parent.parent) ? checker.getPropertyOfType(checker.getTypeFromTypeNode(decl.parent.parent), symbol.name) - : undefined) || symbol; + : undefined; + }) || symbol; } /** diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 02d0979ca1e..e76e21b2963 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -517,29 +517,12 @@ namespace ts.FindAllReferences { const sym = useLhsSymbol ? checker.getSymbolAtLocation(cast(node.left, isPropertyAccessExpression).name) : symbol; // Better detection for GH#20803 if (sym && !(checker.getMergedSymbol(sym.parent).flags & SymbolFlags.Module)) { - Debug.fail(`Special property assignment kind does not have a module as its parent. Assignment is ${showSymbol(sym)}, parent is ${showSymbol(sym.parent)}`); + Debug.fail(`Special property assignment kind does not have a module as its parent. Assignment is ${Debug.showSymbol(sym)}, parent is ${Debug.showSymbol(sym.parent)}`); } return sym && exportInfo(sym, kind); } } - function showSymbol(s: Symbol): string { - const decls = s.declarations.map(d => (ts as any).SyntaxKind[d.kind]).join(","); - const flags = showFlags(s.flags, (ts as any).SymbolFlags); - return `{ declarations: ${decls}, flags: ${flags} }`; - } - - function showFlags(f: number, flags: any) { - const out = []; - for (let pow = 0; pow <= 30; pow++) { - const n = 1 << pow; - if (f & n) { - out.push(flags[n]); - } - } - return out.join("|"); - } - function getImport(): ImportedSymbol | undefined { const isImport = isNodeImport(node); if (!isImport) return undefined; From 2aba29fc32b21cd9f56ea8510c37772735ebcadf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 9 Feb 2018 14:22:46 -0800 Subject: [PATCH 28/32] Add Exclude, Extract, NonNullable, ReturnType, and InstanceType types --- src/lib/es5.d.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 707f749e365..0f773e78786 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1338,6 +1338,31 @@ type Record = { [P in K]: T; }; +/** + * Exclude from T those types that are assignable to U + */ +type Exclude = T extends U ? never : T; + +/** + * Extract from T those types that are assignable to U + */ +type Extract = T extends U ? T : never; + +/** + * Exclude null and undefined from T + */ +type NonNullable = T extends null | undefined ? never : T; + +/** + * Obtain the return type of a function type + */ +type ReturnType any> = T extends (...args: any[]) => infer R ? R : any; + +/** + * Obtain the return type of a constructor function type + */ +type InstanceType any> = T extends new (...args: any[]) => infer R ? R : any; + /** * Marker for contextual 'this' type */ From 92b8ce7821ca9f32cf575d0931fd10364e7a93b1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 9 Feb 2018 14:22:57 -0800 Subject: [PATCH 29/32] Update tests --- .../types/conditional/conditionalTypes1.ts | 30 ++++++++----------- .../types/conditional/inferTypes1.ts | 17 ++++++----- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/tests/cases/conformance/types/conditional/conditionalTypes1.ts b/tests/cases/conformance/types/conditional/conditionalTypes1.ts index 93069138b36..3a6dab9a612 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes1.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes1.ts @@ -1,15 +1,11 @@ // @strict: true // @declaration: true -type Diff = T extends U ? never : T; -type Filter = T extends U ? T : never; -type NonNullable = Diff; +type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" +type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" -type T00 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" -type T01 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" - -type T02 = Diff void), Function>; // string | number -type T03 = Filter void), Function>; // () => void +type T02 = Exclude void), Function>; // string | number +type T03 = Extract void), Function>; // () => void type T04 = NonNullable; // string | number type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[] @@ -33,23 +29,23 @@ function f3(x: Partial[keyof T], y: NonNullable[keyof T]>) { type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean }; -type T10 = Diff; // { k: "c", c: boolean } -type T11 = Filter; // { k: "a", a: number } | { k: "b", b: string } +type T10 = Exclude; // { k: "c", c: boolean } +type T11 = Extract; // { k: "a", a: number } | { k: "b", b: string } -type T12 = Diff; // { k: "c", c: boolean } -type T13 = Filter; // { k: "a", a: number } | { k: "b", b: string } +type T12 = Exclude; // { k: "c", c: boolean } +type T13 = Extract; // { k: "a", a: number } | { k: "b", b: string } -type T14 = Diff; // Options -type T15 = Filter; // never +type T14 = Exclude; // Options +type T15 = Extract; // never -declare function f4(p: K): Filter; +declare function f4(p: K): Extract; let x0 = f4("a"); // { k: "a", a: number } -type OptionsOfKind = Filter; +type OptionsOfKind = Extract; type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } -type Select = Filter; +type Select = Extract; type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string } diff --git a/tests/cases/conformance/types/conditional/inferTypes1.ts b/tests/cases/conformance/types/conditional/inferTypes1.ts index 99cfa8a2460..cb803103bae 100644 --- a/tests/cases/conformance/types/conditional/inferTypes1.ts +++ b/tests/cases/conformance/types/conditional/inferTypes1.ts @@ -15,8 +15,6 @@ type T04 = Unpacked[]>>; // string type T05 = Unpacked; // any type T06 = Unpacked; // never -type ReturnType = T extends ((...args: any[]) => infer R) | (new (...args: any[]) => infer R) ? R : any; - function f1(s: string) { return { a: 1, b: s }; } @@ -31,11 +29,16 @@ type T11 = ReturnType<(s: string) => void>; // void type T12 = ReturnType<(() => T)>; // {} type T13 = ReturnType<(() => T)>; // number[] type T14 = ReturnType; // { a: number, b: string } -type T15 = ReturnType; // C -type T16 = ReturnType; // any -type T17 = ReturnType; // any -type T18 = ReturnType; // Error -type T19 = ReturnType; // any +type T15 = ReturnType; // any +type T16 = ReturnType; // any +type T17 = ReturnType; // Error +type T18 = ReturnType; // Error + +type U10 = InstanceType; // C +type U11 = InstanceType; // any +type U12 = InstanceType; // any +type U13 = InstanceType; // Error +type U14 = InstanceType; // Error type ArgumentType any> = T extends (a: infer A) => any ? A : any; From 11a075c2892fd30b7c3f97ed1a9ca4533f7ea4c7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 9 Feb 2018 14:23:19 -0800 Subject: [PATCH 30/32] Accept new baselines --- .../reference/conditionalTypes1.errors.txt | 90 +- .../baselines/reference/conditionalTypes1.js | 59 +- .../reference/conditionalTypes1.symbols | 1108 ++++++++--------- .../reference/conditionalTypes1.types | 129 +- .../reference/inferTypes1.errors.txt | 60 +- tests/baselines/reference/inferTypes1.js | 17 +- tests/baselines/reference/inferTypes1.symbols | 696 ++++++----- tests/baselines/reference/inferTypes1.types | 46 +- 8 files changed, 1090 insertions(+), 1115 deletions(-) diff --git a/tests/baselines/reference/conditionalTypes1.errors.txt b/tests/baselines/reference/conditionalTypes1.errors.txt index 8b42f006cd4..111b74a830b 100644 --- a/tests/baselines/reference/conditionalTypes1.errors.txt +++ b/tests/baselines/reference/conditionalTypes1.errors.txt @@ -1,16 +1,16 @@ -tests/cases/conformance/types/conditional/conditionalTypes1.ts(16,5): error TS2322: Type 'T' is not assignable to type 'Diff'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(21,5): error TS2322: Type 'T' is not assignable to type 'Diff'. - Type 'string | undefined' is not assignable to type 'Diff'. - Type 'undefined' is not assignable to type 'Diff'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(22,9): error TS2322: Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(12,5): error TS2322: Type 'T' is not assignable to type 'NonNullable'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(17,5): error TS2322: Type 'T' is not assignable to type 'NonNullable'. + Type 'string | undefined' is not assignable to type 'NonNullable'. + Type 'undefined' is not assignable to type 'NonNullable'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(18,9): error TS2322: Type 'T' is not assignable to type 'string'. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(28,5): error TS2322: Type 'Partial[keyof T]' is not assignable to type 'Diff[keyof T], null | undefined>'. - Type 'T[keyof T] | undefined' is not assignable to type 'Diff[keyof T], null | undefined>'. - Type 'undefined' is not assignable to type 'Diff[keyof T], null | undefined>'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(100,5): error TS2322: Type 'Pick' is not assignable to type 'T'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(101,5): error TS2322: Type 'Pick' is not assignable to type 'T'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(103,5): error TS2322: Type 'Pick' is not assignable to type 'Pick'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(24,5): error TS2322: Type 'Partial[keyof T]' is not assignable to type 'NonNullable[keyof T]>'. + Type 'T[keyof T] | undefined' is not assignable to type 'NonNullable[keyof T]>'. + Type 'undefined' is not assignable to type 'NonNullable[keyof T]>'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(96,5): error TS2322: Type 'Pick' is not assignable to type 'T'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(97,5): error TS2322: Type 'Pick' is not assignable to type 'T'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(99,5): error TS2322: Type 'Pick' is not assignable to type 'Pick'. Type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. @@ -19,7 +19,7 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(103,5): error TS2 Type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(105,5): error TS2322: Type 'Pick' is not assignable to type 'Pick'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(101,5): error TS2322: Type 'Pick' is not assignable to type 'Pick'. Type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. @@ -28,49 +28,45 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(105,5): error TS2 Type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(111,5): error TS2322: Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(107,5): error TS2322: Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(112,5): error TS2322: Type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(108,5): error TS2322: Type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'. Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. Type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(113,5): error TS2322: Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(109,5): error TS2322: Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(114,5): error TS2322: Type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(110,5): error TS2322: Type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. Type 'keyof T' is not assignable to type '{ [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'. Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. Type '{ [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(131,10): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(132,5): error TS2542: Index signature in type 'DeepReadonlyArray' only permits reading. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(133,22): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(134,10): error TS2339: Property 'updatePart' does not exist on type 'DeepReadonlyObject'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(156,5): error TS2322: Type 'ZeroOf' is not assignable to type 'T'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(127,10): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(128,5): error TS2542: Index signature in type 'DeepReadonlyArray' only permits reading. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(129,22): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(130,10): error TS2339: Property 'updatePart' does not exist on type 'DeepReadonlyObject'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(152,5): error TS2322: Type 'ZeroOf' is not assignable to type 'T'. Type '0 | (T extends string ? "" : false)' is not assignable to type 'T'. Type '0' is not assignable to type 'T'. Type '"" | 0' is not assignable to type 'T'. Type '""' is not assignable to type 'T'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(157,5): error TS2322: Type 'T' is not assignable to type 'ZeroOf'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(153,5): error TS2322: Type 'T' is not assignable to type 'ZeroOf'. Type 'string | number' is not assignable to type 'ZeroOf'. Type 'string' is not assignable to type 'ZeroOf'. -tests/cases/conformance/types/conditional/conditionalTypes1.ts(247,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'z' must be of type 'T1', but here has type 'Foo'. +tests/cases/conformance/types/conditional/conditionalTypes1.ts(243,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'z' must be of type 'T1', but here has type 'Foo'. ==== tests/cases/conformance/types/conditional/conditionalTypes1.ts (19 errors) ==== - type Diff = T extends U ? never : T; - type Filter = T extends U ? T : never; - type NonNullable = Diff; + type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" + type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" - type T00 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" - type T01 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" - - type T02 = Diff void), Function>; // string | number - type T03 = Filter void), Function>; // () => void + type T02 = Exclude void), Function>; // string | number + type T03 = Extract void), Function>; // () => void type T04 = NonNullable; // string | number type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[] @@ -79,16 +75,16 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(247,9): error TS2 x = y; y = x; // Error ~ -!!! error TS2322: Type 'T' is not assignable to type 'Diff'. +!!! error TS2322: Type 'T' is not assignable to type 'NonNullable'. } function f2(x: T, y: NonNullable) { x = y; y = x; // Error ~ -!!! error TS2322: Type 'T' is not assignable to type 'Diff'. -!!! error TS2322: Type 'string | undefined' is not assignable to type 'Diff'. -!!! error TS2322: Type 'undefined' is not assignable to type 'Diff'. +!!! error TS2322: Type 'T' is not assignable to type 'NonNullable'. +!!! error TS2322: Type 'string | undefined' is not assignable to type 'NonNullable'. +!!! error TS2322: Type 'undefined' is not assignable to type 'NonNullable'. let s1: string = x; // Error ~~ !!! error TS2322: Type 'T' is not assignable to type 'string'. @@ -101,30 +97,30 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(247,9): error TS2 x = y; y = x; // Error ~ -!!! error TS2322: Type 'Partial[keyof T]' is not assignable to type 'Diff[keyof T], null | undefined>'. -!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'Diff[keyof T], null | undefined>'. -!!! error TS2322: Type 'undefined' is not assignable to type 'Diff[keyof T], null | undefined>'. +!!! error TS2322: Type 'Partial[keyof T]' is not assignable to type 'NonNullable[keyof T]>'. +!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'NonNullable[keyof T]>'. +!!! error TS2322: Type 'undefined' is not assignable to type 'NonNullable[keyof T]>'. } type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean }; - type T10 = Diff; // { k: "c", c: boolean } - type T11 = Filter; // { k: "a", a: number } | { k: "b", b: string } + type T10 = Exclude; // { k: "c", c: boolean } + type T11 = Extract; // { k: "a", a: number } | { k: "b", b: string } - type T12 = Diff; // { k: "c", c: boolean } - type T13 = Filter; // { k: "a", a: number } | { k: "b", b: string } + type T12 = Exclude; // { k: "c", c: boolean } + type T13 = Extract; // { k: "a", a: number } | { k: "b", b: string } - type T14 = Diff; // Options - type T15 = Filter; // never + type T14 = Exclude; // Options + type T15 = Extract; // never - declare function f4(p: K): Filter; + declare function f4(p: K): Extract; let x0 = f4("a"); // { k: "a", a: number } - type OptionsOfKind = Filter; + type OptionsOfKind = Extract; type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } - type Select = Filter; + type Select = Extract; type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string } diff --git a/tests/baselines/reference/conditionalTypes1.js b/tests/baselines/reference/conditionalTypes1.js index 403259b049f..399ccb14fb3 100644 --- a/tests/baselines/reference/conditionalTypes1.js +++ b/tests/baselines/reference/conditionalTypes1.js @@ -1,13 +1,9 @@ //// [conditionalTypes1.ts] -type Diff = T extends U ? never : T; -type Filter = T extends U ? T : never; -type NonNullable = Diff; +type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" +type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" -type T00 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" -type T01 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" - -type T02 = Diff void), Function>; // string | number -type T03 = Filter void), Function>; // () => void +type T02 = Exclude void), Function>; // string | number +type T03 = Extract void), Function>; // () => void type T04 = NonNullable; // string | number type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[] @@ -31,23 +27,23 @@ function f3(x: Partial[keyof T], y: NonNullable[keyof T]>) { type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean }; -type T10 = Diff; // { k: "c", c: boolean } -type T11 = Filter; // { k: "a", a: number } | { k: "b", b: string } +type T10 = Exclude; // { k: "c", c: boolean } +type T11 = Extract; // { k: "a", a: number } | { k: "b", b: string } -type T12 = Diff; // { k: "c", c: boolean } -type T13 = Filter; // { k: "a", a: number } | { k: "b", b: string } +type T12 = Exclude; // { k: "c", c: boolean } +type T13 = Extract; // { k: "a", a: number } | { k: "b", b: string } -type T14 = Diff; // Options -type T15 = Filter; // never +type T14 = Exclude; // Options +type T15 = Extract; // never -declare function f4(p: K): Filter; +declare function f4(p: K): Extract; let x0 = f4("a"); // { k: "a", a: number } -type OptionsOfKind = Filter; +type OptionsOfKind = Extract; type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } -type Select = Filter; +type Select = Extract; type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string } @@ -332,13 +328,10 @@ function f33() { //// [conditionalTypes1.d.ts] -declare type Diff = T extends U ? never : T; -declare type Filter = T extends U ? T : never; -declare type NonNullable = Diff; -declare type T00 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; -declare type T01 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; -declare type T02 = Diff void), Function>; -declare type T03 = Filter void), Function>; +declare type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; +declare type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; +declare type T02 = Exclude void), Function>; +declare type T03 = Extract void), Function>; declare type T04 = NonNullable; declare type T05 = NonNullable<(() => string) | string[] | null | undefined>; declare function f1(x: T, y: NonNullable): void; @@ -354,40 +347,40 @@ declare type Options = { k: "c"; c: boolean; }; -declare type T10 = Diff; -declare type T11 = Filter; -declare type T12 = Diff; -declare type T13 = Filter; -declare type T14 = Diff; -declare type T15 = Filter; -declare function f4(p: K): Filter(p: K): Extract; declare let x0: { k: "a"; a: number; }; -declare type OptionsOfKind = Filter = Extract; declare type T16 = OptionsOfKind<"a" | "b">; -declare type Select = Filter = Extract; declare type T17 = Select; diff --git a/tests/baselines/reference/conditionalTypes1.symbols b/tests/baselines/reference/conditionalTypes1.symbols index 883a2d9bda1..cef734c4c4b 100644 --- a/tests/baselines/reference/conditionalTypes1.symbols +++ b/tests/baselines/reference/conditionalTypes1.symbols @@ -1,964 +1,942 @@ === tests/cases/conformance/types/conditional/conditionalTypes1.ts === -type Diff = T extends U ? never : T; ->Diff : Symbol(Diff, Decl(conditionalTypes1.ts, 0, 0)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 0, 10)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 0, 12)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 0, 10)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 0, 12)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 0, 10)) +type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" +>T00 : Symbol(T00, Decl(conditionalTypes1.ts, 0, 0)) +>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) -type Filter = T extends U ? T : never; ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 1, 12)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 1, 14)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 1, 12)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 1, 14)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 1, 12)) +type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" +>T01 : Symbol(T01, Decl(conditionalTypes1.ts, 0, 59)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) -type NonNullable = Diff; ->NonNullable : Symbol(NonNullable, Decl(conditionalTypes1.ts, 1, 44)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 2, 17)) ->Diff : Symbol(Diff, Decl(conditionalTypes1.ts, 0, 0)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 2, 17)) - -type T00 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" ->T00 : Symbol(T00, Decl(conditionalTypes1.ts, 2, 48)) ->Diff : Symbol(Diff, Decl(conditionalTypes1.ts, 0, 0)) - -type T01 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" ->T01 : Symbol(T01, Decl(conditionalTypes1.ts, 4, 56)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) - -type T02 = Diff void), Function>; // string | number ->T02 : Symbol(T02, Decl(conditionalTypes1.ts, 5, 58)) ->Diff : Symbol(Diff, Decl(conditionalTypes1.ts, 0, 0)) +type T02 = Exclude void), Function>; // string | number +>T02 : Symbol(T02, Decl(conditionalTypes1.ts, 1, 59)) +>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) -type T03 = Filter void), Function>; // () => void ->T03 : Symbol(T03, Decl(conditionalTypes1.ts, 7, 58)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) +type T03 = Extract void), Function>; // () => void +>T03 : Symbol(T03, Decl(conditionalTypes1.ts, 3, 61)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) type T04 = NonNullable; // string | number ->T04 : Symbol(T04, Decl(conditionalTypes1.ts, 8, 60)) ->NonNullable : Symbol(NonNullable, Decl(conditionalTypes1.ts, 1, 44)) +>T04 : Symbol(T04, Decl(conditionalTypes1.ts, 4, 61)) +>NonNullable : Symbol(NonNullable, Decl(lib.d.ts, --, --)) type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[] ->T05 : Symbol(T05, Decl(conditionalTypes1.ts, 10, 52)) ->NonNullable : Symbol(NonNullable, Decl(conditionalTypes1.ts, 1, 44)) +>T05 : Symbol(T05, Decl(conditionalTypes1.ts, 6, 52)) +>NonNullable : Symbol(NonNullable, Decl(lib.d.ts, --, --)) function f1(x: T, y: NonNullable) { ->f1 : Symbol(f1, Decl(conditionalTypes1.ts, 11, 69)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 13, 12)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 13, 15)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 13, 12)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 13, 20)) ->NonNullable : Symbol(NonNullable, Decl(conditionalTypes1.ts, 1, 44)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 13, 12)) +>f1 : Symbol(f1, Decl(conditionalTypes1.ts, 7, 69)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 9, 12)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 9, 15)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 9, 12)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 9, 20)) +>NonNullable : Symbol(NonNullable, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 9, 12)) x = y; ->x : Symbol(x, Decl(conditionalTypes1.ts, 13, 15)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 13, 20)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 9, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 9, 20)) y = x; // Error ->y : Symbol(y, Decl(conditionalTypes1.ts, 13, 20)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 13, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 9, 20)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 9, 15)) } function f2(x: T, y: NonNullable) { ->f2 : Symbol(f2, Decl(conditionalTypes1.ts, 16, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 18, 12)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 18, 42)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 18, 12)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 18, 47)) ->NonNullable : Symbol(NonNullable, Decl(conditionalTypes1.ts, 1, 44)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 18, 12)) +>f2 : Symbol(f2, Decl(conditionalTypes1.ts, 12, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 14, 12)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 14, 42)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 14, 12)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 14, 47)) +>NonNullable : Symbol(NonNullable, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 14, 12)) x = y; ->x : Symbol(x, Decl(conditionalTypes1.ts, 18, 42)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 18, 47)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 14, 42)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 14, 47)) y = x; // Error ->y : Symbol(y, Decl(conditionalTypes1.ts, 18, 47)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 18, 42)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 14, 47)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 14, 42)) let s1: string = x; // Error ->s1 : Symbol(s1, Decl(conditionalTypes1.ts, 21, 7)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 18, 42)) +>s1 : Symbol(s1, Decl(conditionalTypes1.ts, 17, 7)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 14, 42)) let s2: string = y; ->s2 : Symbol(s2, Decl(conditionalTypes1.ts, 22, 7)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 18, 47)) +>s2 : Symbol(s2, Decl(conditionalTypes1.ts, 18, 7)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 14, 47)) } function f3(x: Partial[keyof T], y: NonNullable[keyof T]>) { ->f3 : Symbol(f3, Decl(conditionalTypes1.ts, 23, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 25, 12)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 25, 15)) +>f3 : Symbol(f3, Decl(conditionalTypes1.ts, 19, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 21, 12)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 21, 15)) >Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 25, 12)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 25, 12)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 25, 38)) ->NonNullable : Symbol(NonNullable, Decl(conditionalTypes1.ts, 1, 44)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 21, 12)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 21, 12)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 21, 38)) +>NonNullable : Symbol(NonNullable, Decl(lib.d.ts, --, --)) >Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 25, 12)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 25, 12)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 21, 12)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 21, 12)) x = y; ->x : Symbol(x, Decl(conditionalTypes1.ts, 25, 15)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 25, 38)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 21, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 21, 38)) y = x; // Error ->y : Symbol(y, Decl(conditionalTypes1.ts, 25, 38)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 25, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 21, 38)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 21, 15)) } type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean }; ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 30, 16)) ->a : Symbol(a, Decl(conditionalTypes1.ts, 30, 24)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 30, 40)) ->b : Symbol(b, Decl(conditionalTypes1.ts, 30, 48)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 30, 64)) ->c : Symbol(c, Decl(conditionalTypes1.ts, 30, 72)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 26, 16)) +>a : Symbol(a, Decl(conditionalTypes1.ts, 26, 24)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 26, 40)) +>b : Symbol(b, Decl(conditionalTypes1.ts, 26, 48)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 26, 64)) +>c : Symbol(c, Decl(conditionalTypes1.ts, 26, 72)) -type T10 = Diff; // { k: "c", c: boolean } ->T10 : Symbol(T10, Decl(conditionalTypes1.ts, 30, 86)) ->Diff : Symbol(Diff, Decl(conditionalTypes1.ts, 0, 0)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 32, 26)) +type T10 = Exclude; // { k: "c", c: boolean } +>T10 : Symbol(T10, Decl(conditionalTypes1.ts, 26, 86)) +>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 28, 29)) -type T11 = Filter; // { k: "a", a: number } | { k: "b", b: string } ->T11 : Symbol(T11, Decl(conditionalTypes1.ts, 32, 43)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 33, 28)) +type T11 = Extract; // { k: "a", a: number } | { k: "b", b: string } +>T11 : Symbol(T11, Decl(conditionalTypes1.ts, 28, 46)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 29, 29)) -type T12 = Diff; // { k: "c", c: boolean } ->T12 : Symbol(T12, Decl(conditionalTypes1.ts, 33, 45)) ->Diff : Symbol(Diff, Decl(conditionalTypes1.ts, 0, 0)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 35, 26)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 35, 39)) +type T12 = Exclude; // { k: "c", c: boolean } +>T12 : Symbol(T12, Decl(conditionalTypes1.ts, 29, 46)) +>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 31, 29)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 31, 42)) -type T13 = Filter; // { k: "a", a: number } | { k: "b", b: string } ->T13 : Symbol(T13, Decl(conditionalTypes1.ts, 35, 50)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 36, 28)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 36, 41)) +type T13 = Extract; // { k: "a", a: number } | { k: "b", b: string } +>T13 : Symbol(T13, Decl(conditionalTypes1.ts, 31, 53)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 32, 29)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 32, 42)) -type T14 = Diff; // Options ->T14 : Symbol(T14, Decl(conditionalTypes1.ts, 36, 52)) ->Diff : Symbol(Diff, Decl(conditionalTypes1.ts, 0, 0)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->q : Symbol(q, Decl(conditionalTypes1.ts, 38, 26)) +type T14 = Exclude; // Options +>T14 : Symbol(T14, Decl(conditionalTypes1.ts, 32, 53)) +>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>q : Symbol(q, Decl(conditionalTypes1.ts, 34, 29)) -type T15 = Filter; // never ->T15 : Symbol(T15, Decl(conditionalTypes1.ts, 38, 37)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->q : Symbol(q, Decl(conditionalTypes1.ts, 39, 28)) +type T15 = Extract; // never +>T15 : Symbol(T15, Decl(conditionalTypes1.ts, 34, 40)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>q : Symbol(q, Decl(conditionalTypes1.ts, 35, 29)) -declare function f4(p: K): Filter; ->f4 : Symbol(f4, Decl(conditionalTypes1.ts, 39, 39)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 41, 20)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 41, 38)) ->p : Symbol(p, Decl(conditionalTypes1.ts, 41, 57)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 41, 38)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 41, 20)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 41, 75)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 41, 38)) +declare function f4(p: K): Extract; +>f4 : Symbol(f4, Decl(conditionalTypes1.ts, 35, 40)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 37, 20)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 37, 38)) +>p : Symbol(p, Decl(conditionalTypes1.ts, 37, 57)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 37, 38)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 37, 20)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 37, 76)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 37, 38)) let x0 = f4("a"); // { k: "a", a: number } ->x0 : Symbol(x0, Decl(conditionalTypes1.ts, 42, 3)) ->f4 : Symbol(f4, Decl(conditionalTypes1.ts, 39, 39)) +>x0 : Symbol(x0, Decl(conditionalTypes1.ts, 38, 3)) +>f4 : Symbol(f4, Decl(conditionalTypes1.ts, 35, 40)) -type OptionsOfKind = Filter; ->OptionsOfKind : Symbol(OptionsOfKind, Decl(conditionalTypes1.ts, 42, 17)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 44, 19)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) ->k : Symbol(k, Decl(conditionalTypes1.ts, 44, 62)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 44, 19)) +type OptionsOfKind = Extract; +>OptionsOfKind : Symbol(OptionsOfKind, Decl(conditionalTypes1.ts, 38, 17)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 40, 19)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) +>k : Symbol(k, Decl(conditionalTypes1.ts, 40, 63)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 40, 19)) type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } ->T16 : Symbol(T16, Decl(conditionalTypes1.ts, 44, 71)) ->OptionsOfKind : Symbol(OptionsOfKind, Decl(conditionalTypes1.ts, 42, 17)) +>T16 : Symbol(T16, Decl(conditionalTypes1.ts, 40, 72)) +>OptionsOfKind : Symbol(OptionsOfKind, Decl(conditionalTypes1.ts, 38, 17)) -type Select = Filter; ->Select : Symbol(Select, Decl(conditionalTypes1.ts, 46, 36)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 48, 12)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 48, 14)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 48, 12)) ->V : Symbol(V, Decl(conditionalTypes1.ts, 48, 33)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 48, 12)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 48, 14)) ->Filter : Symbol(Filter, Decl(conditionalTypes1.ts, 0, 42)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 48, 12)) ->P : Symbol(P, Decl(conditionalTypes1.ts, 48, 65)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 48, 14)) ->V : Symbol(V, Decl(conditionalTypes1.ts, 48, 33)) +type Select = Extract; +>Select : Symbol(Select, Decl(conditionalTypes1.ts, 42, 36)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 44, 12)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 44, 14)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 44, 12)) +>V : Symbol(V, Decl(conditionalTypes1.ts, 44, 33)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 44, 12)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 44, 14)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 44, 12)) +>P : Symbol(P, Decl(conditionalTypes1.ts, 44, 66)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 44, 14)) +>V : Symbol(V, Decl(conditionalTypes1.ts, 44, 33)) type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string } ->T17 : Symbol(T17, Decl(conditionalTypes1.ts, 48, 79)) ->Select : Symbol(Select, Decl(conditionalTypes1.ts, 46, 36)) ->Options : Symbol(Options, Decl(conditionalTypes1.ts, 28, 1)) +>T17 : Symbol(T17, Decl(conditionalTypes1.ts, 44, 80)) +>Select : Symbol(Select, Decl(conditionalTypes1.ts, 42, 36)) +>Options : Symbol(Options, Decl(conditionalTypes1.ts, 24, 1)) type TypeName = ->TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 50, 43)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 52, 14)) +>TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 46, 43)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 48, 14)) T extends string ? "string" : ->T : Symbol(T, Decl(conditionalTypes1.ts, 52, 14)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 48, 14)) T extends number ? "number" : ->T : Symbol(T, Decl(conditionalTypes1.ts, 52, 14)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 48, 14)) T extends boolean ? "boolean" : ->T : Symbol(T, Decl(conditionalTypes1.ts, 52, 14)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 48, 14)) T extends undefined ? "undefined" : ->T : Symbol(T, Decl(conditionalTypes1.ts, 52, 14)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 48, 14)) T extends Function ? "function" : ->T : Symbol(T, Decl(conditionalTypes1.ts, 52, 14)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 48, 14)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) "object"; type T20 = TypeName void)>; // "string" | "function" ->T20 : Symbol(T20, Decl(conditionalTypes1.ts, 58, 13)) ->TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 50, 43)) +>T20 : Symbol(T20, Decl(conditionalTypes1.ts, 54, 13)) +>TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 46, 43)) type T21 = TypeName; // "string" | "number" | "boolean" | "undefined" | "function" | "object" ->T21 : Symbol(T21, Decl(conditionalTypes1.ts, 60, 43)) ->TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 50, 43)) +>T21 : Symbol(T21, Decl(conditionalTypes1.ts, 56, 43)) +>TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 46, 43)) type T22 = TypeName; // "string" | "number" | "boolean" | "undefined" | "function" | "object" ->T22 : Symbol(T22, Decl(conditionalTypes1.ts, 61, 25)) ->TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 50, 43)) +>T22 : Symbol(T22, Decl(conditionalTypes1.ts, 57, 25)) +>TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 46, 43)) type T23 = TypeName<{}>; // "object" ->T23 : Symbol(T23, Decl(conditionalTypes1.ts, 62, 27)) ->TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 50, 43)) +>T23 : Symbol(T23, Decl(conditionalTypes1.ts, 58, 27)) +>TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 46, 43)) type KnockoutObservable = { object: T }; ->KnockoutObservable : Symbol(KnockoutObservable, Decl(conditionalTypes1.ts, 63, 24)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 65, 24)) ->object : Symbol(object, Decl(conditionalTypes1.ts, 65, 30)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 65, 24)) +>KnockoutObservable : Symbol(KnockoutObservable, Decl(conditionalTypes1.ts, 59, 24)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 61, 24)) +>object : Symbol(object, Decl(conditionalTypes1.ts, 61, 30)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 61, 24)) type KnockoutObservableArray = { array: T }; ->KnockoutObservableArray : Symbol(KnockoutObservableArray, Decl(conditionalTypes1.ts, 65, 43)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 66, 29)) ->array : Symbol(array, Decl(conditionalTypes1.ts, 66, 35)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 66, 29)) +>KnockoutObservableArray : Symbol(KnockoutObservableArray, Decl(conditionalTypes1.ts, 61, 43)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 62, 29)) +>array : Symbol(array, Decl(conditionalTypes1.ts, 62, 35)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 62, 29)) type KnockedOut = T extends any[] ? KnockoutObservableArray : KnockoutObservable; ->KnockedOut : Symbol(KnockedOut, Decl(conditionalTypes1.ts, 66, 47)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 68, 16)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 68, 16)) ->KnockoutObservableArray : Symbol(KnockoutObservableArray, Decl(conditionalTypes1.ts, 65, 43)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 68, 16)) ->KnockoutObservable : Symbol(KnockoutObservable, Decl(conditionalTypes1.ts, 63, 24)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 68, 16)) +>KnockedOut : Symbol(KnockedOut, Decl(conditionalTypes1.ts, 62, 47)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 64, 16)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 64, 16)) +>KnockoutObservableArray : Symbol(KnockoutObservableArray, Decl(conditionalTypes1.ts, 61, 43)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 64, 16)) +>KnockoutObservable : Symbol(KnockoutObservable, Decl(conditionalTypes1.ts, 59, 24)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 64, 16)) type KnockedOutObj = { ->KnockedOutObj : Symbol(KnockedOutObj, Decl(conditionalTypes1.ts, 68, 98)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 70, 19)) +>KnockedOutObj : Symbol(KnockedOutObj, Decl(conditionalTypes1.ts, 64, 98)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 66, 19)) [P in keyof T]: KnockedOut; ->P : Symbol(P, Decl(conditionalTypes1.ts, 71, 5)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 70, 19)) ->KnockedOut : Symbol(KnockedOut, Decl(conditionalTypes1.ts, 66, 47)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 70, 19)) ->P : Symbol(P, Decl(conditionalTypes1.ts, 71, 5)) +>P : Symbol(P, Decl(conditionalTypes1.ts, 67, 5)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 66, 19)) +>KnockedOut : Symbol(KnockedOut, Decl(conditionalTypes1.ts, 62, 47)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 66, 19)) +>P : Symbol(P, Decl(conditionalTypes1.ts, 67, 5)) } interface Item { ->Item : Symbol(Item, Decl(conditionalTypes1.ts, 72, 1)) +>Item : Symbol(Item, Decl(conditionalTypes1.ts, 68, 1)) id: number; ->id : Symbol(Item.id, Decl(conditionalTypes1.ts, 74, 16)) +>id : Symbol(Item.id, Decl(conditionalTypes1.ts, 70, 16)) name: string; ->name : Symbol(Item.name, Decl(conditionalTypes1.ts, 75, 15)) +>name : Symbol(Item.name, Decl(conditionalTypes1.ts, 71, 15)) subitems: string[]; ->subitems : Symbol(Item.subitems, Decl(conditionalTypes1.ts, 76, 17)) +>subitems : Symbol(Item.subitems, Decl(conditionalTypes1.ts, 72, 17)) } type KOItem = KnockedOutObj; ->KOItem : Symbol(KOItem, Decl(conditionalTypes1.ts, 78, 1)) ->KnockedOutObj : Symbol(KnockedOutObj, Decl(conditionalTypes1.ts, 68, 98)) ->Item : Symbol(Item, Decl(conditionalTypes1.ts, 72, 1)) +>KOItem : Symbol(KOItem, Decl(conditionalTypes1.ts, 74, 1)) +>KnockedOutObj : Symbol(KnockedOutObj, Decl(conditionalTypes1.ts, 64, 98)) +>Item : Symbol(Item, Decl(conditionalTypes1.ts, 68, 1)) interface Part { ->Part : Symbol(Part, Decl(conditionalTypes1.ts, 80, 34)) +>Part : Symbol(Part, Decl(conditionalTypes1.ts, 76, 34)) id: number; ->id : Symbol(Part.id, Decl(conditionalTypes1.ts, 82, 16)) +>id : Symbol(Part.id, Decl(conditionalTypes1.ts, 78, 16)) name: string; ->name : Symbol(Part.name, Decl(conditionalTypes1.ts, 83, 15)) +>name : Symbol(Part.name, Decl(conditionalTypes1.ts, 79, 15)) subparts: Part[]; ->subparts : Symbol(Part.subparts, Decl(conditionalTypes1.ts, 84, 17)) ->Part : Symbol(Part, Decl(conditionalTypes1.ts, 80, 34)) +>subparts : Symbol(Part.subparts, Decl(conditionalTypes1.ts, 80, 17)) +>Part : Symbol(Part, Decl(conditionalTypes1.ts, 76, 34)) updatePart(newName: string): void; ->updatePart : Symbol(Part.updatePart, Decl(conditionalTypes1.ts, 85, 21)) ->newName : Symbol(newName, Decl(conditionalTypes1.ts, 86, 15)) +>updatePart : Symbol(Part.updatePart, Decl(conditionalTypes1.ts, 81, 21)) +>newName : Symbol(newName, Decl(conditionalTypes1.ts, 82, 15)) } type FunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]; ->FunctionPropertyNames : Symbol(FunctionPropertyNames, Decl(conditionalTypes1.ts, 87, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 89, 27)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 89, 35)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 89, 27)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 89, 27)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 89, 35)) +>FunctionPropertyNames : Symbol(FunctionPropertyNames, Decl(conditionalTypes1.ts, 83, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 85, 27)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 85, 35)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 85, 27)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 85, 27)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 85, 35)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 89, 35)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 89, 27)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 85, 35)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 85, 27)) type FunctionProperties = Pick>; ->FunctionProperties : Symbol(FunctionProperties, Decl(conditionalTypes1.ts, 89, 95)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 90, 24)) +>FunctionProperties : Symbol(FunctionProperties, Decl(conditionalTypes1.ts, 85, 95)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 86, 24)) >Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 90, 24)) ->FunctionPropertyNames : Symbol(FunctionPropertyNames, Decl(conditionalTypes1.ts, 87, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 90, 24)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 86, 24)) +>FunctionPropertyNames : Symbol(FunctionPropertyNames, Decl(conditionalTypes1.ts, 83, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 86, 24)) type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]; ->NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 90, 63)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 92, 30)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 92, 38)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 92, 30)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 92, 30)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 92, 38)) +>NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 86, 63)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 88, 30)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 88, 38)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 88, 30)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 88, 30)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 88, 38)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->K : Symbol(K, Decl(conditionalTypes1.ts, 92, 38)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 92, 30)) +>K : Symbol(K, Decl(conditionalTypes1.ts, 88, 38)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 88, 30)) type NonFunctionProperties = Pick>; ->NonFunctionProperties : Symbol(NonFunctionProperties, Decl(conditionalTypes1.ts, 92, 98)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 93, 27)) +>NonFunctionProperties : Symbol(NonFunctionProperties, Decl(conditionalTypes1.ts, 88, 98)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 89, 27)) >Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 93, 27)) ->NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 90, 63)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 93, 27)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 89, 27)) +>NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 86, 63)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 89, 27)) type T30 = FunctionProperties; ->T30 : Symbol(T30, Decl(conditionalTypes1.ts, 93, 69)) ->FunctionProperties : Symbol(FunctionProperties, Decl(conditionalTypes1.ts, 89, 95)) ->Part : Symbol(Part, Decl(conditionalTypes1.ts, 80, 34)) +>T30 : Symbol(T30, Decl(conditionalTypes1.ts, 89, 69)) +>FunctionProperties : Symbol(FunctionProperties, Decl(conditionalTypes1.ts, 85, 95)) +>Part : Symbol(Part, Decl(conditionalTypes1.ts, 76, 34)) type T31 = NonFunctionProperties; ->T31 : Symbol(T31, Decl(conditionalTypes1.ts, 95, 36)) ->NonFunctionProperties : Symbol(NonFunctionProperties, Decl(conditionalTypes1.ts, 92, 98)) ->Part : Symbol(Part, Decl(conditionalTypes1.ts, 80, 34)) +>T31 : Symbol(T31, Decl(conditionalTypes1.ts, 91, 36)) +>NonFunctionProperties : Symbol(NonFunctionProperties, Decl(conditionalTypes1.ts, 88, 98)) +>Part : Symbol(Part, Decl(conditionalTypes1.ts, 76, 34)) function f7(x: T, y: FunctionProperties, z: NonFunctionProperties) { ->f7 : Symbol(f7, Decl(conditionalTypes1.ts, 96, 39)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 98, 12)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 98, 15)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 98, 12)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 98, 20)) ->FunctionProperties : Symbol(FunctionProperties, Decl(conditionalTypes1.ts, 89, 95)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 98, 12)) ->z : Symbol(z, Decl(conditionalTypes1.ts, 98, 46)) ->NonFunctionProperties : Symbol(NonFunctionProperties, Decl(conditionalTypes1.ts, 92, 98)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 98, 12)) +>f7 : Symbol(f7, Decl(conditionalTypes1.ts, 92, 39)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 94, 12)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 94, 15)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 94, 12)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 94, 20)) +>FunctionProperties : Symbol(FunctionProperties, Decl(conditionalTypes1.ts, 85, 95)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 94, 12)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 94, 46)) +>NonFunctionProperties : Symbol(NonFunctionProperties, Decl(conditionalTypes1.ts, 88, 98)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 94, 12)) x = y; // Error ->x : Symbol(x, Decl(conditionalTypes1.ts, 98, 15)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 98, 20)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 94, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 94, 20)) x = z; // Error ->x : Symbol(x, Decl(conditionalTypes1.ts, 98, 15)) ->z : Symbol(z, Decl(conditionalTypes1.ts, 98, 46)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 94, 15)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 94, 46)) y = x; ->y : Symbol(y, Decl(conditionalTypes1.ts, 98, 20)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 98, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 94, 20)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 94, 15)) y = z; // Error ->y : Symbol(y, Decl(conditionalTypes1.ts, 98, 20)) ->z : Symbol(z, Decl(conditionalTypes1.ts, 98, 46)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 94, 20)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 94, 46)) z = x; ->z : Symbol(z, Decl(conditionalTypes1.ts, 98, 46)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 98, 15)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 94, 46)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 94, 15)) z = y; // Error ->z : Symbol(z, Decl(conditionalTypes1.ts, 98, 46)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 98, 20)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 94, 46)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 94, 20)) } function f8(x: keyof T, y: FunctionPropertyNames, z: NonFunctionPropertyNames) { ->f8 : Symbol(f8, Decl(conditionalTypes1.ts, 105, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 107, 12)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 107, 15)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 107, 12)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 107, 26)) ->FunctionPropertyNames : Symbol(FunctionPropertyNames, Decl(conditionalTypes1.ts, 87, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 107, 12)) ->z : Symbol(z, Decl(conditionalTypes1.ts, 107, 55)) ->NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 90, 63)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 107, 12)) +>f8 : Symbol(f8, Decl(conditionalTypes1.ts, 101, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 103, 12)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 103, 15)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 103, 12)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 103, 26)) +>FunctionPropertyNames : Symbol(FunctionPropertyNames, Decl(conditionalTypes1.ts, 83, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 103, 12)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 103, 55)) +>NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 86, 63)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 103, 12)) x = y; ->x : Symbol(x, Decl(conditionalTypes1.ts, 107, 15)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 107, 26)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 103, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 103, 26)) x = z; ->x : Symbol(x, Decl(conditionalTypes1.ts, 107, 15)) ->z : Symbol(z, Decl(conditionalTypes1.ts, 107, 55)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 103, 15)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 103, 55)) y = x; // Error ->y : Symbol(y, Decl(conditionalTypes1.ts, 107, 26)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 107, 15)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 103, 26)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 103, 15)) y = z; // Error ->y : Symbol(y, Decl(conditionalTypes1.ts, 107, 26)) ->z : Symbol(z, Decl(conditionalTypes1.ts, 107, 55)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 103, 26)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 103, 55)) z = x; // Error ->z : Symbol(z, Decl(conditionalTypes1.ts, 107, 55)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 107, 15)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 103, 55)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 103, 15)) z = y; // Error ->z : Symbol(z, Decl(conditionalTypes1.ts, 107, 55)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 107, 26)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 103, 55)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 103, 26)) } type DeepReadonly = ->DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 114, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 116, 18)) +>DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 110, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 112, 18)) T extends any[] ? DeepReadonlyArray : ->T : Symbol(T, Decl(conditionalTypes1.ts, 116, 18)) ->DeepReadonlyArray : Symbol(DeepReadonlyArray, Decl(conditionalTypes1.ts, 119, 6)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 116, 18)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 112, 18)) +>DeepReadonlyArray : Symbol(DeepReadonlyArray, Decl(conditionalTypes1.ts, 115, 6)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 112, 18)) T extends object ? DeepReadonlyObject : ->T : Symbol(T, Decl(conditionalTypes1.ts, 116, 18)) ->DeepReadonlyObject : Symbol(DeepReadonlyObject, Decl(conditionalTypes1.ts, 121, 72)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 116, 18)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 112, 18)) +>DeepReadonlyObject : Symbol(DeepReadonlyObject, Decl(conditionalTypes1.ts, 117, 72)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 112, 18)) T; ->T : Symbol(T, Decl(conditionalTypes1.ts, 116, 18)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 112, 18)) interface DeepReadonlyArray extends ReadonlyArray> {} ->DeepReadonlyArray : Symbol(DeepReadonlyArray, Decl(conditionalTypes1.ts, 119, 6)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 121, 28)) +>DeepReadonlyArray : Symbol(DeepReadonlyArray, Decl(conditionalTypes1.ts, 115, 6)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 117, 28)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) ->DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 114, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 121, 28)) +>DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 110, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 117, 28)) type DeepReadonlyObject = { ->DeepReadonlyObject : Symbol(DeepReadonlyObject, Decl(conditionalTypes1.ts, 121, 72)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 123, 24)) +>DeepReadonlyObject : Symbol(DeepReadonlyObject, Decl(conditionalTypes1.ts, 117, 72)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 119, 24)) readonly [P in NonFunctionPropertyNames]: DeepReadonly; ->P : Symbol(P, Decl(conditionalTypes1.ts, 124, 14)) ->NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 90, 63)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 123, 24)) ->DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 114, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 123, 24)) ->P : Symbol(P, Decl(conditionalTypes1.ts, 124, 14)) +>P : Symbol(P, Decl(conditionalTypes1.ts, 120, 14)) +>NonFunctionPropertyNames : Symbol(NonFunctionPropertyNames, Decl(conditionalTypes1.ts, 86, 63)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 119, 24)) +>DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 110, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 119, 24)) +>P : Symbol(P, Decl(conditionalTypes1.ts, 120, 14)) }; function f10(part: DeepReadonly) { ->f10 : Symbol(f10, Decl(conditionalTypes1.ts, 125, 2)) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) ->DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 114, 1)) ->Part : Symbol(Part, Decl(conditionalTypes1.ts, 80, 34)) +>f10 : Symbol(f10, Decl(conditionalTypes1.ts, 121, 2)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) +>DeepReadonly : Symbol(DeepReadonly, Decl(conditionalTypes1.ts, 110, 1)) +>Part : Symbol(Part, Decl(conditionalTypes1.ts, 76, 34)) let name: string = part.name; ->name : Symbol(name, Decl(conditionalTypes1.ts, 128, 7)) +>name : Symbol(name, Decl(conditionalTypes1.ts, 124, 7)) >part.name : Symbol(name) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >name : Symbol(name) let id: number = part.subparts[0].id; ->id : Symbol(id, Decl(conditionalTypes1.ts, 129, 7)) +>id : Symbol(id, Decl(conditionalTypes1.ts, 125, 7)) >part.subparts[0].id : Symbol(id) >part.subparts : Symbol(subparts) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >subparts : Symbol(subparts) >id : Symbol(id) part.id = part.id; // Error >part.id : Symbol(id) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >id : Symbol(id) >part.id : Symbol(id) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >id : Symbol(id) part.subparts[0] = part.subparts[0]; // Error >part.subparts : Symbol(subparts) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >subparts : Symbol(subparts) >part.subparts : Symbol(subparts) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >subparts : Symbol(subparts) part.subparts[0].id = part.subparts[0].id; // Error >part.subparts[0].id : Symbol(id) >part.subparts : Symbol(subparts) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >subparts : Symbol(subparts) >id : Symbol(id) >part.subparts[0].id : Symbol(id) >part.subparts : Symbol(subparts) ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) >subparts : Symbol(subparts) >id : Symbol(id) part.updatePart("hello"); // Error ->part : Symbol(part, Decl(conditionalTypes1.ts, 127, 13)) +>part : Symbol(part, Decl(conditionalTypes1.ts, 123, 13)) } type ZeroOf = T extends number ? 0 : T extends string ? "" : false; ->ZeroOf : Symbol(ZeroOf, Decl(conditionalTypes1.ts, 134, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 136, 12)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 136, 12)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 136, 12)) +>ZeroOf : Symbol(ZeroOf, Decl(conditionalTypes1.ts, 130, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 132, 12)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 132, 12)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 132, 12)) function zeroOf(value: T) { ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 138, 16)) ->value : Symbol(value, Decl(conditionalTypes1.ts, 138, 53)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 138, 16)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 134, 16)) +>value : Symbol(value, Decl(conditionalTypes1.ts, 134, 53)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 134, 16)) return >(typeof value === "number" ? 0 : typeof value === "string" ? "" : false); ->ZeroOf : Symbol(ZeroOf, Decl(conditionalTypes1.ts, 134, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 138, 16)) ->value : Symbol(value, Decl(conditionalTypes1.ts, 138, 53)) ->value : Symbol(value, Decl(conditionalTypes1.ts, 138, 53)) +>ZeroOf : Symbol(ZeroOf, Decl(conditionalTypes1.ts, 130, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 134, 16)) +>value : Symbol(value, Decl(conditionalTypes1.ts, 134, 53)) +>value : Symbol(value, Decl(conditionalTypes1.ts, 134, 53)) } function f20(n: number, b: boolean, x: number | boolean, y: T) { ->f20 : Symbol(f20, Decl(conditionalTypes1.ts, 140, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 142, 13)) ->n : Symbol(n, Decl(conditionalTypes1.ts, 142, 31)) ->b : Symbol(b, Decl(conditionalTypes1.ts, 142, 41)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 142, 53)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 142, 74)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 142, 13)) +>f20 : Symbol(f20, Decl(conditionalTypes1.ts, 136, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 138, 13)) +>n : Symbol(n, Decl(conditionalTypes1.ts, 138, 31)) +>b : Symbol(b, Decl(conditionalTypes1.ts, 138, 41)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 138, 53)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 138, 74)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 138, 13)) zeroOf(5); // 0 ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) zeroOf("hello"); // "" ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) zeroOf(true); // false ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) zeroOf(n); // 0 ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) ->n : Symbol(n, Decl(conditionalTypes1.ts, 142, 31)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) +>n : Symbol(n, Decl(conditionalTypes1.ts, 138, 31)) zeroOf(b); // False ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) ->b : Symbol(b, Decl(conditionalTypes1.ts, 142, 41)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) +>b : Symbol(b, Decl(conditionalTypes1.ts, 138, 41)) zeroOf(x); // 0 | false ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 142, 53)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 138, 53)) zeroOf(y); // ZeroOf ->zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 136, 104)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 142, 74)) +>zeroOf : Symbol(zeroOf, Decl(conditionalTypes1.ts, 132, 104)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 138, 74)) } function f21(x: T, y: ZeroOf) { ->f21 : Symbol(f21, Decl(conditionalTypes1.ts, 150, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 152, 13)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 152, 40)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 152, 13)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 152, 45)) ->ZeroOf : Symbol(ZeroOf, Decl(conditionalTypes1.ts, 134, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 152, 13)) +>f21 : Symbol(f21, Decl(conditionalTypes1.ts, 146, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 148, 13)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 148, 40)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 148, 13)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 148, 45)) +>ZeroOf : Symbol(ZeroOf, Decl(conditionalTypes1.ts, 130, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 148, 13)) let z1: number | string = y; ->z1 : Symbol(z1, Decl(conditionalTypes1.ts, 153, 7)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 152, 45)) +>z1 : Symbol(z1, Decl(conditionalTypes1.ts, 149, 7)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 148, 45)) let z2: 0 | "" = y; ->z2 : Symbol(z2, Decl(conditionalTypes1.ts, 154, 7)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 152, 45)) +>z2 : Symbol(z2, Decl(conditionalTypes1.ts, 150, 7)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 148, 45)) x = y; // Error ->x : Symbol(x, Decl(conditionalTypes1.ts, 152, 40)) ->y : Symbol(y, Decl(conditionalTypes1.ts, 152, 45)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 148, 40)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 148, 45)) y = x; // Error ->y : Symbol(y, Decl(conditionalTypes1.ts, 152, 45)) ->x : Symbol(x, Decl(conditionalTypes1.ts, 152, 40)) +>y : Symbol(y, Decl(conditionalTypes1.ts, 148, 45)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 148, 40)) } type Extends = T extends U ? true : false; ->Extends : Symbol(Extends, Decl(conditionalTypes1.ts, 157, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 159, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 159, 15)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 159, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 159, 15)) +>Extends : Symbol(Extends, Decl(conditionalTypes1.ts, 153, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 155, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 155, 15)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 155, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 155, 15)) type If = C extends true ? T : F; ->If : Symbol(If, Decl(conditionalTypes1.ts, 159, 48)) ->C : Symbol(C, Decl(conditionalTypes1.ts, 160, 8)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 160, 26)) ->F : Symbol(F, Decl(conditionalTypes1.ts, 160, 29)) ->C : Symbol(C, Decl(conditionalTypes1.ts, 160, 8)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 160, 26)) ->F : Symbol(F, Decl(conditionalTypes1.ts, 160, 29)) +>If : Symbol(If, Decl(conditionalTypes1.ts, 155, 48)) +>C : Symbol(C, Decl(conditionalTypes1.ts, 156, 8)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 156, 26)) +>F : Symbol(F, Decl(conditionalTypes1.ts, 156, 29)) +>C : Symbol(C, Decl(conditionalTypes1.ts, 156, 8)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 156, 26)) +>F : Symbol(F, Decl(conditionalTypes1.ts, 156, 29)) type Not = If; ->Not : Symbol(Not, Decl(conditionalTypes1.ts, 160, 58)) ->C : Symbol(C, Decl(conditionalTypes1.ts, 161, 9)) ->If : Symbol(If, Decl(conditionalTypes1.ts, 159, 48)) ->C : Symbol(C, Decl(conditionalTypes1.ts, 161, 9)) +>Not : Symbol(Not, Decl(conditionalTypes1.ts, 156, 58)) +>C : Symbol(C, Decl(conditionalTypes1.ts, 157, 9)) +>If : Symbol(If, Decl(conditionalTypes1.ts, 155, 48)) +>C : Symbol(C, Decl(conditionalTypes1.ts, 157, 9)) type And = If; ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) ->A : Symbol(A, Decl(conditionalTypes1.ts, 162, 9)) ->B : Symbol(B, Decl(conditionalTypes1.ts, 162, 27)) ->If : Symbol(If, Decl(conditionalTypes1.ts, 159, 48)) ->A : Symbol(A, Decl(conditionalTypes1.ts, 162, 9)) ->B : Symbol(B, Decl(conditionalTypes1.ts, 162, 27)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 158, 9)) +>B : Symbol(B, Decl(conditionalTypes1.ts, 158, 27)) +>If : Symbol(If, Decl(conditionalTypes1.ts, 155, 48)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 158, 9)) +>B : Symbol(B, Decl(conditionalTypes1.ts, 158, 27)) type Or = If; ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) ->A : Symbol(A, Decl(conditionalTypes1.ts, 163, 8)) ->B : Symbol(B, Decl(conditionalTypes1.ts, 163, 26)) ->If : Symbol(If, Decl(conditionalTypes1.ts, 159, 48)) ->A : Symbol(A, Decl(conditionalTypes1.ts, 163, 8)) ->B : Symbol(B, Decl(conditionalTypes1.ts, 163, 26)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 159, 8)) +>B : Symbol(B, Decl(conditionalTypes1.ts, 159, 26)) +>If : Symbol(If, Decl(conditionalTypes1.ts, 155, 48)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 159, 8)) +>B : Symbol(B, Decl(conditionalTypes1.ts, 159, 26)) type IsString = Extends; ->IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 163, 63)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 165, 14)) ->Extends : Symbol(Extends, Decl(conditionalTypes1.ts, 157, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 165, 14)) +>IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 159, 63)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 161, 14)) +>Extends : Symbol(Extends, Decl(conditionalTypes1.ts, 153, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 161, 14)) type Q1 = IsString; // false ->Q1 : Symbol(Q1, Decl(conditionalTypes1.ts, 165, 38)) ->IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 163, 63)) +>Q1 : Symbol(Q1, Decl(conditionalTypes1.ts, 161, 38)) +>IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 159, 63)) type Q2 = IsString<"abc">; // true ->Q2 : Symbol(Q2, Decl(conditionalTypes1.ts, 167, 27)) ->IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 163, 63)) +>Q2 : Symbol(Q2, Decl(conditionalTypes1.ts, 163, 27)) +>IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 159, 63)) type Q3 = IsString; // boolean ->Q3 : Symbol(Q3, Decl(conditionalTypes1.ts, 168, 26)) ->IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 163, 63)) +>Q3 : Symbol(Q3, Decl(conditionalTypes1.ts, 164, 26)) +>IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 159, 63)) type Q4 = IsString; // boolean ->Q4 : Symbol(Q4, Decl(conditionalTypes1.ts, 169, 24)) ->IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 163, 63)) +>Q4 : Symbol(Q4, Decl(conditionalTypes1.ts, 165, 24)) +>IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 159, 63)) type N1 = Not; // true ->N1 : Symbol(N1, Decl(conditionalTypes1.ts, 170, 26)) ->Not : Symbol(Not, Decl(conditionalTypes1.ts, 160, 58)) +>N1 : Symbol(N1, Decl(conditionalTypes1.ts, 166, 26)) +>Not : Symbol(Not, Decl(conditionalTypes1.ts, 156, 58)) type N2 = Not; // false ->N2 : Symbol(N2, Decl(conditionalTypes1.ts, 172, 21)) ->Not : Symbol(Not, Decl(conditionalTypes1.ts, 160, 58)) +>N2 : Symbol(N2, Decl(conditionalTypes1.ts, 168, 21)) +>Not : Symbol(Not, Decl(conditionalTypes1.ts, 156, 58)) type N3 = Not; // boolean ->N3 : Symbol(N3, Decl(conditionalTypes1.ts, 173, 20)) ->Not : Symbol(Not, Decl(conditionalTypes1.ts, 160, 58)) +>N3 : Symbol(N3, Decl(conditionalTypes1.ts, 169, 20)) +>Not : Symbol(Not, Decl(conditionalTypes1.ts, 156, 58)) type A1 = And; // false ->A1 : Symbol(A1, Decl(conditionalTypes1.ts, 174, 23)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A1 : Symbol(A1, Decl(conditionalTypes1.ts, 170, 23)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A2 = And; // false ->A2 : Symbol(A2, Decl(conditionalTypes1.ts, 176, 28)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A2 : Symbol(A2, Decl(conditionalTypes1.ts, 172, 28)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A3 = And; // false ->A3 : Symbol(A3, Decl(conditionalTypes1.ts, 177, 27)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A3 : Symbol(A3, Decl(conditionalTypes1.ts, 173, 27)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A4 = And; // true ->A4 : Symbol(A4, Decl(conditionalTypes1.ts, 178, 27)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A4 : Symbol(A4, Decl(conditionalTypes1.ts, 174, 27)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A5 = And; // false ->A5 : Symbol(A5, Decl(conditionalTypes1.ts, 179, 26)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A5 : Symbol(A5, Decl(conditionalTypes1.ts, 175, 26)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A6 = And; // false ->A6 : Symbol(A6, Decl(conditionalTypes1.ts, 180, 30)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A6 : Symbol(A6, Decl(conditionalTypes1.ts, 176, 30)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A7 = And; // boolean ->A7 : Symbol(A7, Decl(conditionalTypes1.ts, 181, 30)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A7 : Symbol(A7, Decl(conditionalTypes1.ts, 177, 30)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A8 = And; // boolean ->A8 : Symbol(A8, Decl(conditionalTypes1.ts, 182, 29)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A8 : Symbol(A8, Decl(conditionalTypes1.ts, 178, 29)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type A9 = And; // boolean ->A9 : Symbol(A9, Decl(conditionalTypes1.ts, 183, 29)) ->And : Symbol(And, Decl(conditionalTypes1.ts, 161, 49)) +>A9 : Symbol(A9, Decl(conditionalTypes1.ts, 179, 29)) +>And : Symbol(And, Decl(conditionalTypes1.ts, 157, 49)) type O1 = Or; // false ->O1 : Symbol(O1, Decl(conditionalTypes1.ts, 184, 32)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O1 : Symbol(O1, Decl(conditionalTypes1.ts, 180, 32)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O2 = Or; // true ->O2 : Symbol(O2, Decl(conditionalTypes1.ts, 186, 27)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O2 : Symbol(O2, Decl(conditionalTypes1.ts, 182, 27)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O3 = Or; // true ->O3 : Symbol(O3, Decl(conditionalTypes1.ts, 187, 26)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O3 : Symbol(O3, Decl(conditionalTypes1.ts, 183, 26)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O4 = Or; // true ->O4 : Symbol(O4, Decl(conditionalTypes1.ts, 188, 26)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O4 : Symbol(O4, Decl(conditionalTypes1.ts, 184, 26)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O5 = Or; // boolean ->O5 : Symbol(O5, Decl(conditionalTypes1.ts, 189, 25)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O5 : Symbol(O5, Decl(conditionalTypes1.ts, 185, 25)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O6 = Or; // boolean ->O6 : Symbol(O6, Decl(conditionalTypes1.ts, 190, 29)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O6 : Symbol(O6, Decl(conditionalTypes1.ts, 186, 29)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O7 = Or; // true ->O7 : Symbol(O7, Decl(conditionalTypes1.ts, 191, 29)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O7 : Symbol(O7, Decl(conditionalTypes1.ts, 187, 29)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O8 = Or; // true ->O8 : Symbol(O8, Decl(conditionalTypes1.ts, 192, 28)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O8 : Symbol(O8, Decl(conditionalTypes1.ts, 188, 28)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type O9 = Or; // boolean ->O9 : Symbol(O9, Decl(conditionalTypes1.ts, 193, 28)) ->Or : Symbol(Or, Decl(conditionalTypes1.ts, 162, 65)) +>O9 : Symbol(O9, Decl(conditionalTypes1.ts, 189, 28)) +>Or : Symbol(Or, Decl(conditionalTypes1.ts, 158, 65)) type T40 = never extends never ? true : false; // true ->T40 : Symbol(T40, Decl(conditionalTypes1.ts, 194, 31)) +>T40 : Symbol(T40, Decl(conditionalTypes1.ts, 190, 31)) type T41 = number extends never ? true : false; // false ->T41 : Symbol(T41, Decl(conditionalTypes1.ts, 196, 46)) +>T41 : Symbol(T41, Decl(conditionalTypes1.ts, 192, 46)) type T42 = never extends number ? true : false; // boolean ->T42 : Symbol(T42, Decl(conditionalTypes1.ts, 197, 47)) +>T42 : Symbol(T42, Decl(conditionalTypes1.ts, 193, 47)) type IsNever = T extends never ? true : false; ->IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 198, 47)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 200, 13)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 200, 13)) +>IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 194, 47)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 196, 13)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 196, 13)) type T50 = IsNever; // true ->T50 : Symbol(T50, Decl(conditionalTypes1.ts, 200, 49)) ->IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 198, 47)) +>T50 : Symbol(T50, Decl(conditionalTypes1.ts, 196, 49)) +>IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 194, 47)) type T51 = IsNever; // false ->T51 : Symbol(T51, Decl(conditionalTypes1.ts, 202, 26)) ->IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 198, 47)) +>T51 : Symbol(T51, Decl(conditionalTypes1.ts, 198, 26)) +>IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 194, 47)) type T52 = IsNever; // false ->T52 : Symbol(T52, Decl(conditionalTypes1.ts, 203, 27)) ->IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 198, 47)) +>T52 : Symbol(T52, Decl(conditionalTypes1.ts, 199, 27)) +>IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 194, 47)) // Repros from #21664 type Eq = T extends U ? U extends T ? true : false : false; ->Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 208, 8)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 208, 10)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 208, 8)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 208, 10)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 208, 10)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 208, 8)) +>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 200, 24)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 204, 8)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 204, 10)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 204, 8)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 204, 10)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 204, 10)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 204, 8)) type T60 = Eq; // true ->T60 : Symbol(T60, Decl(conditionalTypes1.ts, 208, 65)) ->Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24)) +>T60 : Symbol(T60, Decl(conditionalTypes1.ts, 204, 65)) +>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 200, 24)) type T61 = Eq; // false ->T61 : Symbol(T61, Decl(conditionalTypes1.ts, 209, 26)) ->Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24)) +>T61 : Symbol(T61, Decl(conditionalTypes1.ts, 205, 26)) +>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 200, 24)) type T62 = Eq; // false ->T62 : Symbol(T62, Decl(conditionalTypes1.ts, 210, 27)) ->Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24)) +>T62 : Symbol(T62, Decl(conditionalTypes1.ts, 206, 27)) +>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 200, 24)) type T63 = Eq; // true ->T63 : Symbol(T63, Decl(conditionalTypes1.ts, 211, 27)) ->Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24)) +>T63 : Symbol(T63, Decl(conditionalTypes1.ts, 207, 27)) +>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 200, 24)) type Eq1 = Eq extends false ? false : true; ->Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 214, 9)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 214, 11)) ->Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 214, 9)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 214, 11)) +>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 208, 28)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 210, 9)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 210, 11)) +>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 200, 24)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 210, 9)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 210, 11)) type T70 = Eq1; // true ->T70 : Symbol(T70, Decl(conditionalTypes1.ts, 214, 55)) ->Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28)) +>T70 : Symbol(T70, Decl(conditionalTypes1.ts, 210, 55)) +>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 208, 28)) type T71 = Eq1; // false ->T71 : Symbol(T71, Decl(conditionalTypes1.ts, 215, 27)) ->Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28)) +>T71 : Symbol(T71, Decl(conditionalTypes1.ts, 211, 27)) +>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 208, 28)) type T72 = Eq1; // false ->T72 : Symbol(T72, Decl(conditionalTypes1.ts, 216, 28)) ->Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28)) +>T72 : Symbol(T72, Decl(conditionalTypes1.ts, 212, 28)) +>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 208, 28)) type T73 = Eq1; // true ->T73 : Symbol(T73, Decl(conditionalTypes1.ts, 217, 28)) ->Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28)) +>T73 : Symbol(T73, Decl(conditionalTypes1.ts, 213, 28)) +>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 208, 28)) type Eq2 = Eq extends true ? true : false; ->Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 220, 9)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 220, 11)) ->Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 220, 9)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 220, 11)) +>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 214, 29)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 216, 9)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 216, 11)) +>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 200, 24)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 216, 9)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 216, 11)) type T80 = Eq2; // true ->T80 : Symbol(T80, Decl(conditionalTypes1.ts, 220, 54)) ->Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29)) +>T80 : Symbol(T80, Decl(conditionalTypes1.ts, 216, 54)) +>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 214, 29)) type T81 = Eq2; // false ->T81 : Symbol(T81, Decl(conditionalTypes1.ts, 221, 27)) ->Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29)) +>T81 : Symbol(T81, Decl(conditionalTypes1.ts, 217, 27)) +>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 214, 29)) type T82 = Eq2; // false ->T82 : Symbol(T82, Decl(conditionalTypes1.ts, 222, 28)) ->Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29)) +>T82 : Symbol(T82, Decl(conditionalTypes1.ts, 218, 28)) +>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 214, 29)) type T83 = Eq2; // true ->T83 : Symbol(T83, Decl(conditionalTypes1.ts, 223, 28)) ->Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29)) +>T83 : Symbol(T83, Decl(conditionalTypes1.ts, 219, 28)) +>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 214, 29)) // Repro from #21756 type Foo = T extends string ? boolean : number; ->Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 224, 29)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 228, 9)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 228, 9)) +>Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 220, 29)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 224, 9)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 224, 9)) type Bar = T extends string ? boolean : number; ->Bar : Symbol(Bar, Decl(conditionalTypes1.ts, 228, 50)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 229, 9)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 229, 9)) +>Bar : Symbol(Bar, Decl(conditionalTypes1.ts, 224, 50)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 225, 9)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 225, 9)) const convert = (value: Foo): Bar => value; ->convert : Symbol(convert, Decl(conditionalTypes1.ts, 230, 5)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 230, 17)) ->value : Symbol(value, Decl(conditionalTypes1.ts, 230, 20)) ->Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 224, 29)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 230, 17)) ->Bar : Symbol(Bar, Decl(conditionalTypes1.ts, 228, 50)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 230, 17)) ->value : Symbol(value, Decl(conditionalTypes1.ts, 230, 20)) +>convert : Symbol(convert, Decl(conditionalTypes1.ts, 226, 5)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 226, 17)) +>value : Symbol(value, Decl(conditionalTypes1.ts, 226, 20)) +>Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 220, 29)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 226, 17)) +>Bar : Symbol(Bar, Decl(conditionalTypes1.ts, 224, 50)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 226, 17)) +>value : Symbol(value, Decl(conditionalTypes1.ts, 226, 20)) type Baz = Foo; ->Baz : Symbol(Baz, Decl(conditionalTypes1.ts, 230, 52)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 232, 9)) ->Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 224, 29)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 232, 9)) +>Baz : Symbol(Baz, Decl(conditionalTypes1.ts, 226, 52)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 228, 9)) +>Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 220, 29)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 228, 9)) const convert2 = (value: Foo): Baz => value; ->convert2 : Symbol(convert2, Decl(conditionalTypes1.ts, 233, 5)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 233, 18)) ->value : Symbol(value, Decl(conditionalTypes1.ts, 233, 21)) ->Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 224, 29)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 233, 18)) ->Baz : Symbol(Baz, Decl(conditionalTypes1.ts, 230, 52)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 233, 18)) ->value : Symbol(value, Decl(conditionalTypes1.ts, 233, 21)) +>convert2 : Symbol(convert2, Decl(conditionalTypes1.ts, 229, 5)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 229, 18)) +>value : Symbol(value, Decl(conditionalTypes1.ts, 229, 21)) +>Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 220, 29)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 229, 18)) +>Baz : Symbol(Baz, Decl(conditionalTypes1.ts, 226, 52)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 229, 18)) +>value : Symbol(value, Decl(conditionalTypes1.ts, 229, 21)) function f31() { ->f31 : Symbol(f31, Decl(conditionalTypes1.ts, 233, 53)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 235, 13)) +>f31 : Symbol(f31, Decl(conditionalTypes1.ts, 229, 53)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 231, 13)) type T1 = T extends string ? boolean : number; ->T1 : Symbol(T1, Decl(conditionalTypes1.ts, 235, 19)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 235, 13)) +>T1 : Symbol(T1, Decl(conditionalTypes1.ts, 231, 19)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 231, 13)) type T2 = T extends string ? boolean : number; ->T2 : Symbol(T2, Decl(conditionalTypes1.ts, 236, 50)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 235, 13)) +>T2 : Symbol(T2, Decl(conditionalTypes1.ts, 232, 50)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 231, 13)) var x: T1; ->x : Symbol(x, Decl(conditionalTypes1.ts, 238, 7), Decl(conditionalTypes1.ts, 239, 7)) ->T1 : Symbol(T1, Decl(conditionalTypes1.ts, 235, 19)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 234, 7), Decl(conditionalTypes1.ts, 235, 7)) +>T1 : Symbol(T1, Decl(conditionalTypes1.ts, 231, 19)) var x: T2; ->x : Symbol(x, Decl(conditionalTypes1.ts, 238, 7), Decl(conditionalTypes1.ts, 239, 7)) ->T2 : Symbol(T2, Decl(conditionalTypes1.ts, 236, 50)) +>x : Symbol(x, Decl(conditionalTypes1.ts, 234, 7), Decl(conditionalTypes1.ts, 235, 7)) +>T2 : Symbol(T2, Decl(conditionalTypes1.ts, 232, 50)) } function f32() { ->f32 : Symbol(f32, Decl(conditionalTypes1.ts, 240, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 242, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 242, 15)) +>f32 : Symbol(f32, Decl(conditionalTypes1.ts, 236, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 238, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 238, 15)) type T1 = T & U extends string ? boolean : number; ->T1 : Symbol(T1, Decl(conditionalTypes1.ts, 242, 22)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 242, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 242, 15)) +>T1 : Symbol(T1, Decl(conditionalTypes1.ts, 238, 22)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 238, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 238, 15)) type T2 = Foo; ->T2 : Symbol(T2, Decl(conditionalTypes1.ts, 243, 54)) ->Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 224, 29)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 242, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 242, 15)) +>T2 : Symbol(T2, Decl(conditionalTypes1.ts, 239, 54)) +>Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 220, 29)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 238, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 238, 15)) var z: T1; ->z : Symbol(z, Decl(conditionalTypes1.ts, 245, 7), Decl(conditionalTypes1.ts, 246, 7)) ->T1 : Symbol(T1, Decl(conditionalTypes1.ts, 242, 22)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 241, 7), Decl(conditionalTypes1.ts, 242, 7)) +>T1 : Symbol(T1, Decl(conditionalTypes1.ts, 238, 22)) var z: T2; // Error, T2 is distributive, T1 isn't ->z : Symbol(z, Decl(conditionalTypes1.ts, 245, 7), Decl(conditionalTypes1.ts, 246, 7)) ->T2 : Symbol(T2, Decl(conditionalTypes1.ts, 243, 54)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 241, 7), Decl(conditionalTypes1.ts, 242, 7)) +>T2 : Symbol(T2, Decl(conditionalTypes1.ts, 239, 54)) } function f33() { ->f33 : Symbol(f33, Decl(conditionalTypes1.ts, 247, 1)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 249, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 249, 15)) +>f33 : Symbol(f33, Decl(conditionalTypes1.ts, 243, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 245, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 245, 15)) type T1 = Foo; ->T1 : Symbol(T1, Decl(conditionalTypes1.ts, 249, 22)) ->Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 224, 29)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 249, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 249, 15)) +>T1 : Symbol(T1, Decl(conditionalTypes1.ts, 245, 22)) +>Foo : Symbol(Foo, Decl(conditionalTypes1.ts, 220, 29)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 245, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 245, 15)) type T2 = Bar; ->T2 : Symbol(T2, Decl(conditionalTypes1.ts, 250, 25)) ->Bar : Symbol(Bar, Decl(conditionalTypes1.ts, 228, 50)) ->T : Symbol(T, Decl(conditionalTypes1.ts, 249, 13)) ->U : Symbol(U, Decl(conditionalTypes1.ts, 249, 15)) +>T2 : Symbol(T2, Decl(conditionalTypes1.ts, 246, 25)) +>Bar : Symbol(Bar, Decl(conditionalTypes1.ts, 224, 50)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 245, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 245, 15)) var z: T1; ->z : Symbol(z, Decl(conditionalTypes1.ts, 252, 7), Decl(conditionalTypes1.ts, 253, 7)) ->T1 : Symbol(T1, Decl(conditionalTypes1.ts, 249, 22)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 248, 7), Decl(conditionalTypes1.ts, 249, 7)) +>T1 : Symbol(T1, Decl(conditionalTypes1.ts, 245, 22)) var z: T2; ->z : Symbol(z, Decl(conditionalTypes1.ts, 252, 7), Decl(conditionalTypes1.ts, 253, 7)) ->T2 : Symbol(T2, Decl(conditionalTypes1.ts, 250, 25)) +>z : Symbol(z, Decl(conditionalTypes1.ts, 248, 7), Decl(conditionalTypes1.ts, 249, 7)) +>T2 : Symbol(T2, Decl(conditionalTypes1.ts, 246, 25)) } diff --git a/tests/baselines/reference/conditionalTypes1.types b/tests/baselines/reference/conditionalTypes1.types index 9c68f394094..eb17cb31350 100644 --- a/tests/baselines/reference/conditionalTypes1.types +++ b/tests/baselines/reference/conditionalTypes1.types @@ -1,91 +1,68 @@ === tests/cases/conformance/types/conditional/conditionalTypes1.ts === -type Diff = T extends U ? never : T; ->Diff : Diff ->T : T ->U : U ->T : T ->U : U ->T : T - -type Filter = T extends U ? T : never; ->Filter : Filter ->T : T ->U : U ->T : T ->U : U ->T : T - -type NonNullable = Diff; ->NonNullable : Diff ->T : T ->Diff : Diff ->T : T ->null : null - -type T00 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" +type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" >T00 : "b" | "d" ->Diff : Diff +>Exclude : Exclude -type T01 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" +type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" >T01 : "a" | "c" ->Filter : Filter +>Extract : Extract -type T02 = Diff void), Function>; // string | number +type T02 = Exclude void), Function>; // string | number >T02 : string | number ->Diff : Diff +>Exclude : Exclude >Function : Function -type T03 = Filter void), Function>; // () => void +type T03 = Extract void), Function>; // () => void >T03 : () => void ->Filter : Filter +>Extract : Extract >Function : Function type T04 = NonNullable; // string | number >T04 : string | number ->NonNullable : Diff +>NonNullable : NonNullable type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[] >T05 : (() => string) | string[] ->NonNullable : Diff +>NonNullable : NonNullable >null : null function f1(x: T, y: NonNullable) { ->f1 : (x: T, y: Diff) => void +>f1 : (x: T, y: NonNullable) => void >T : T >x : T >T : T ->y : Diff ->NonNullable : Diff +>y : NonNullable +>NonNullable : NonNullable >T : T x = y; ->x = y : Diff +>x = y : NonNullable >x : T ->y : Diff +>y : NonNullable y = x; // Error >y = x : T ->y : Diff +>y : NonNullable >x : T } function f2(x: T, y: NonNullable) { ->f2 : (x: T, y: Diff) => void +>f2 : (x: T, y: NonNullable) => void >T : T >x : T >T : T ->y : Diff ->NonNullable : Diff +>y : NonNullable +>NonNullable : NonNullable >T : T x = y; ->x = y : Diff +>x = y : NonNullable >x : T ->y : Diff +>y : NonNullable y = x; // Error >y = x : T ->y : Diff +>y : NonNullable >x : T let s1: string = x; // Error @@ -94,30 +71,30 @@ function f2(x: T, y: NonNullable) { let s2: string = y; >s2 : string ->y : Diff +>y : NonNullable } function f3(x: Partial[keyof T], y: NonNullable[keyof T]>) { ->f3 : (x: Partial[keyof T], y: Diff[keyof T], null | undefined>) => void +>f3 : (x: Partial[keyof T], y: NonNullable[keyof T]>) => void >T : T >x : Partial[keyof T] >Partial : Partial >T : T >T : T ->y : Diff[keyof T], null | undefined> ->NonNullable : Diff +>y : NonNullable[keyof T]> +>NonNullable : NonNullable >Partial : Partial >T : T >T : T x = y; ->x = y : Diff[keyof T], null | undefined> +>x = y : NonNullable[keyof T]> >x : Partial[keyof T] ->y : Diff[keyof T], null | undefined> +>y : NonNullable[keyof T]> y = x; // Error >y = x : Partial[keyof T] ->y : Diff[keyof T], null | undefined> +>y : NonNullable[keyof T]> >x : Partial[keyof T] } @@ -130,52 +107,52 @@ type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: bool >k : "c" >c : boolean -type T10 = Diff; // { k: "c", c: boolean } +type T10 = Exclude; // { k: "c", c: boolean } >T10 : { k: "c"; c: boolean; } ->Diff : Diff +>Exclude : Exclude >Options : Options >k : "a" | "b" -type T11 = Filter; // { k: "a", a: number } | { k: "b", b: string } +type T11 = Extract; // { k: "a", a: number } | { k: "b", b: string } >T11 : { k: "a"; a: number; } | { k: "b"; b: string; } ->Filter : Filter +>Extract : Extract >Options : Options >k : "a" | "b" -type T12 = Diff; // { k: "c", c: boolean } +type T12 = Exclude; // { k: "c", c: boolean } >T12 : { k: "c"; c: boolean; } ->Diff : Diff +>Exclude : Exclude >Options : Options >k : "a" >k : "b" -type T13 = Filter; // { k: "a", a: number } | { k: "b", b: string } +type T13 = Extract; // { k: "a", a: number } | { k: "b", b: string } >T13 : { k: "a"; a: number; } | { k: "b"; b: string; } ->Filter : Filter +>Extract : Extract >Options : Options >k : "a" >k : "b" -type T14 = Diff; // Options +type T14 = Exclude; // Options >T14 : Options ->Diff : Diff +>Exclude : Exclude >Options : Options >q : "a" -type T15 = Filter; // never +type T15 = Extract; // never >T15 : never ->Filter : Filter +>Extract : Extract >Options : Options >q : "a" -declare function f4(p: K): Filter; ->f4 : (p: K) => Filter +declare function f4(p: K): Extract; +>f4 : (p: K) => Extract >T : T >Options : Options >K : K >p : K >K : K ->Filter : Filter +>Extract : Extract >T : T >k : K >K : K @@ -183,31 +160,31 @@ declare function f4(p: K): Filterx0 : { k: "a"; a: number; } >f4("a") : { k: "a"; a: number; } ->f4 : (p: K) => Filter +>f4 : (p: K) => Extract >"a" : "a" -type OptionsOfKind = Filter; ->OptionsOfKind : Filter<{ k: "a"; a: number; }, { k: K; }> | Filter<{ k: "b"; b: string; }, { k: K; }> | Filter<{ k: "c"; c: boolean; }, { k: K; }> +type OptionsOfKind = Extract; +>OptionsOfKind : Extract<{ k: "a"; a: number; }, { k: K; }> | Extract<{ k: "b"; b: string; }, { k: K; }> | Extract<{ k: "c"; c: boolean; }, { k: K; }> >K : K >Options : Options ->Filter : Filter +>Extract : Extract >Options : Options >k : K >K : K type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } >T16 : { k: "a"; a: number; } | { k: "b"; b: string; } ->OptionsOfKind : Filter<{ k: "a"; a: number; }, { k: K; }> | Filter<{ k: "b"; b: string; }, { k: K; }> | Filter<{ k: "c"; c: boolean; }, { k: K; }> +>OptionsOfKind : Extract<{ k: "a"; a: number; }, { k: K; }> | Extract<{ k: "b"; b: string; }, { k: K; }> | Extract<{ k: "c"; c: boolean; }, { k: K; }> -type Select = Filter; ->Select : Filter +type Select = Extract; +>Select : Extract >T : T >K : K >T : T >V : V >T : T >K : K ->Filter : Filter +>Extract : Extract >T : T >P : P >K : K @@ -215,7 +192,7 @@ type Select = Filter; type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string } >T17 : { k: "a"; a: number; } | { k: "b"; b: string; } ->Select : Filter +>Select : Extract >Options : Options type TypeName = diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt index 80edc31d37c..acc4b9029b1 100644 --- a/tests/baselines/reference/inferTypes1.errors.txt +++ b/tests/baselines/reference/inferTypes1.errors.txt @@ -1,21 +1,26 @@ -tests/cases/conformance/types/conditional/inferTypes1.ts(34,23): error TS2344: Type 'string' does not satisfy the constraint 'Function'. -tests/cases/conformance/types/conditional/inferTypes1.ts(43,25): error TS2344: Type '(x: string, y: string) => number' does not satisfy the constraint '(x: any) => any'. -tests/cases/conformance/types/conditional/inferTypes1.ts(44,25): error TS2344: Type 'Function' does not satisfy the constraint '(x: any) => any'. +tests/cases/conformance/types/conditional/inferTypes1.ts(31,23): error TS2344: Type 'string' does not satisfy the constraint '(...args: any[]) => any'. +tests/cases/conformance/types/conditional/inferTypes1.ts(32,23): error TS2344: Type 'Function' does not satisfy the constraint '(...args: any[]) => any'. + Type 'Function' provides no match for the signature '(...args: any[]): any'. +tests/cases/conformance/types/conditional/inferTypes1.ts(37,25): error TS2344: Type 'string' does not satisfy the constraint 'new (...args: any[]) => any'. +tests/cases/conformance/types/conditional/inferTypes1.ts(38,25): error TS2344: Type 'Function' does not satisfy the constraint 'new (...args: any[]) => any'. + Type 'Function' provides no match for the signature 'new (...args: any[]): any'. +tests/cases/conformance/types/conditional/inferTypes1.ts(46,25): error TS2344: Type '(x: string, y: string) => number' does not satisfy the constraint '(x: any) => any'. +tests/cases/conformance/types/conditional/inferTypes1.ts(47,25): error TS2344: Type 'Function' does not satisfy the constraint '(x: any) => any'. Type 'Function' provides no match for the signature '(x: any): any'. -tests/cases/conformance/types/conditional/inferTypes1.ts(70,12): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. -tests/cases/conformance/types/conditional/inferTypes1.ts(71,15): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. -tests/cases/conformance/types/conditional/inferTypes1.ts(71,41): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. -tests/cases/conformance/types/conditional/inferTypes1.ts(71,51): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. -tests/cases/conformance/types/conditional/inferTypes1.ts(72,15): error TS2304: Cannot find name 'U'. -tests/cases/conformance/types/conditional/inferTypes1.ts(72,15): error TS4081: Exported type alias 'T62' has or is using private name 'U'. -tests/cases/conformance/types/conditional/inferTypes1.ts(72,43): error TS2304: Cannot find name 'U'. -tests/cases/conformance/types/conditional/inferTypes1.ts(72,43): error TS4081: Exported type alias 'T62' has or is using private name 'U'. -tests/cases/conformance/types/conditional/inferTypes1.ts(78,44): error TS2344: Type 'U' does not satisfy the constraint 'string'. +tests/cases/conformance/types/conditional/inferTypes1.ts(73,12): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. +tests/cases/conformance/types/conditional/inferTypes1.ts(74,15): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. +tests/cases/conformance/types/conditional/inferTypes1.ts(74,41): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. +tests/cases/conformance/types/conditional/inferTypes1.ts(74,51): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. +tests/cases/conformance/types/conditional/inferTypes1.ts(75,15): error TS2304: Cannot find name 'U'. +tests/cases/conformance/types/conditional/inferTypes1.ts(75,15): error TS4081: Exported type alias 'T62' has or is using private name 'U'. +tests/cases/conformance/types/conditional/inferTypes1.ts(75,43): error TS2304: Cannot find name 'U'. +tests/cases/conformance/types/conditional/inferTypes1.ts(75,43): error TS4081: Exported type alias 'T62' has or is using private name 'U'. +tests/cases/conformance/types/conditional/inferTypes1.ts(81,44): error TS2344: Type 'U' does not satisfy the constraint 'string'. Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/conditional/inferTypes1.ts(131,40): error TS2322: Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/conditional/inferTypes1.ts(134,40): error TS2322: Type 'T' is not assignable to type 'string'. -==== tests/cases/conformance/types/conditional/inferTypes1.ts (13 errors) ==== +==== tests/cases/conformance/types/conditional/inferTypes1.ts (16 errors) ==== type Unpacked = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : @@ -30,8 +35,6 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(131,40): error TS2322: type T05 = Unpacked; // any type T06 = Unpacked; // never - type ReturnType = T extends ((...args: any[]) => infer R) | (new (...args: any[]) => infer R) ? R : any; - function f1(s: string) { return { a: 1, b: s }; } @@ -46,13 +49,26 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(131,40): error TS2322: type T12 = ReturnType<(() => T)>; // {} type T13 = ReturnType<(() => T)>; // number[] type T14 = ReturnType; // { a: number, b: string } - type T15 = ReturnType; // C - type T16 = ReturnType; // any - type T17 = ReturnType; // any - type T18 = ReturnType; // Error + type T15 = ReturnType; // any + type T16 = ReturnType; // any + type T17 = ReturnType; // Error ~~~~~~ -!!! error TS2344: Type 'string' does not satisfy the constraint 'Function'. - type T19 = ReturnType; // any +!!! error TS2344: Type 'string' does not satisfy the constraint '(...args: any[]) => any'. + type T18 = ReturnType; // Error + ~~~~~~~~ +!!! error TS2344: Type 'Function' does not satisfy the constraint '(...args: any[]) => any'. +!!! error TS2344: Type 'Function' provides no match for the signature '(...args: any[]): any'. + + type U10 = InstanceType; // C + type U11 = InstanceType; // any + type U12 = InstanceType; // any + type U13 = InstanceType; // Error + ~~~~~~ +!!! error TS2344: Type 'string' does not satisfy the constraint 'new (...args: any[]) => any'. + type U14 = InstanceType; // Error + ~~~~~~~~ +!!! error TS2344: Type 'Function' does not satisfy the constraint 'new (...args: any[]) => any'. +!!! error TS2344: Type 'Function' provides no match for the signature 'new (...args: any[]): any'. type ArgumentType any> = T extends (a: infer A) => any ? A : any; diff --git a/tests/baselines/reference/inferTypes1.js b/tests/baselines/reference/inferTypes1.js index 21cada9c71b..146acdc1ce7 100644 --- a/tests/baselines/reference/inferTypes1.js +++ b/tests/baselines/reference/inferTypes1.js @@ -13,8 +13,6 @@ type T04 = Unpacked[]>>; // string type T05 = Unpacked; // any type T06 = Unpacked; // never -type ReturnType = T extends ((...args: any[]) => infer R) | (new (...args: any[]) => infer R) ? R : any; - function f1(s: string) { return { a: 1, b: s }; } @@ -29,11 +27,16 @@ type T11 = ReturnType<(s: string) => void>; // void type T12 = ReturnType<(() => T)>; // {} type T13 = ReturnType<(() => T)>; // number[] type T14 = ReturnType; // { a: number, b: string } -type T15 = ReturnType; // C -type T16 = ReturnType; // any -type T17 = ReturnType; // any -type T18 = ReturnType; // Error -type T19 = ReturnType; // any +type T15 = ReturnType; // any +type T16 = ReturnType; // any +type T17 = ReturnType; // Error +type T18 = ReturnType; // Error + +type U10 = InstanceType; // C +type U11 = InstanceType; // any +type U12 = InstanceType; // any +type U13 = InstanceType; // Error +type U14 = InstanceType; // Error type ArgumentType any> = T extends (a: infer A) => any ? A : any; diff --git a/tests/baselines/reference/inferTypes1.symbols b/tests/baselines/reference/inferTypes1.symbols index 6e8a9670f29..138f60aaf49 100644 --- a/tests/baselines/reference/inferTypes1.symbols +++ b/tests/baselines/reference/inferTypes1.symbols @@ -54,518 +54,524 @@ type T06 = Unpacked; // never >T06 : Symbol(T06, Decl(inferTypes1.ts, 11, 25)) >Unpacked : Symbol(Unpacked, Decl(inferTypes1.ts, 0, 0)) -type ReturnType = T extends ((...args: any[]) => infer R) | (new (...args: any[]) => infer R) ? R : any; ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) ->T : Symbol(T, Decl(inferTypes1.ts, 14, 16)) ->Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(inferTypes1.ts, 14, 16)) ->args : Symbol(args, Decl(inferTypes1.ts, 14, 50)) ->R : Symbol(R, Decl(inferTypes1.ts, 14, 74), Decl(inferTypes1.ts, 14, 110)) ->args : Symbol(args, Decl(inferTypes1.ts, 14, 86)) ->R : Symbol(R, Decl(inferTypes1.ts, 14, 74), Decl(inferTypes1.ts, 14, 110)) ->R : Symbol(R, Decl(inferTypes1.ts, 14, 74), Decl(inferTypes1.ts, 14, 110)) - function f1(s: string) { ->f1 : Symbol(f1, Decl(inferTypes1.ts, 14, 124)) ->s : Symbol(s, Decl(inferTypes1.ts, 16, 12)) +>f1 : Symbol(f1, Decl(inferTypes1.ts, 12, 27)) +>s : Symbol(s, Decl(inferTypes1.ts, 14, 12)) return { a: 1, b: s }; ->a : Symbol(a, Decl(inferTypes1.ts, 17, 12)) ->b : Symbol(b, Decl(inferTypes1.ts, 17, 18)) ->s : Symbol(s, Decl(inferTypes1.ts, 16, 12)) +>a : Symbol(a, Decl(inferTypes1.ts, 15, 12)) +>b : Symbol(b, Decl(inferTypes1.ts, 15, 18)) +>s : Symbol(s, Decl(inferTypes1.ts, 14, 12)) } class C { ->C : Symbol(C, Decl(inferTypes1.ts, 18, 1)) +>C : Symbol(C, Decl(inferTypes1.ts, 16, 1)) x = 0; ->x : Symbol(C.x, Decl(inferTypes1.ts, 20, 9)) +>x : Symbol(C.x, Decl(inferTypes1.ts, 18, 9)) y = 0; ->y : Symbol(C.y, Decl(inferTypes1.ts, 21, 10)) +>y : Symbol(C.y, Decl(inferTypes1.ts, 19, 10)) } type T10 = ReturnType<() => string>; // string ->T10 : Symbol(T10, Decl(inferTypes1.ts, 23, 1)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) +>T10 : Symbol(T10, Decl(inferTypes1.ts, 21, 1)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) type T11 = ReturnType<(s: string) => void>; // void ->T11 : Symbol(T11, Decl(inferTypes1.ts, 25, 36)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) ->s : Symbol(s, Decl(inferTypes1.ts, 26, 23)) +>T11 : Symbol(T11, Decl(inferTypes1.ts, 23, 36)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferTypes1.ts, 24, 23)) type T12 = ReturnType<(() => T)>; // {} ->T12 : Symbol(T12, Decl(inferTypes1.ts, 26, 43)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) ->T : Symbol(T, Decl(inferTypes1.ts, 27, 24)) ->T : Symbol(T, Decl(inferTypes1.ts, 27, 24)) +>T12 : Symbol(T12, Decl(inferTypes1.ts, 24, 43)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(inferTypes1.ts, 25, 24)) +>T : Symbol(T, Decl(inferTypes1.ts, 25, 24)) type T13 = ReturnType<(() => T)>; // number[] ->T13 : Symbol(T13, Decl(inferTypes1.ts, 27, 36)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) ->T : Symbol(T, Decl(inferTypes1.ts, 28, 24)) ->U : Symbol(U, Decl(inferTypes1.ts, 28, 36)) ->U : Symbol(U, Decl(inferTypes1.ts, 28, 36)) ->T : Symbol(T, Decl(inferTypes1.ts, 28, 24)) +>T13 : Symbol(T13, Decl(inferTypes1.ts, 25, 36)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(inferTypes1.ts, 26, 24)) +>U : Symbol(U, Decl(inferTypes1.ts, 26, 36)) +>U : Symbol(U, Decl(inferTypes1.ts, 26, 36)) +>T : Symbol(T, Decl(inferTypes1.ts, 26, 24)) type T14 = ReturnType; // { a: number, b: string } ->T14 : Symbol(T14, Decl(inferTypes1.ts, 28, 66)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) ->f1 : Symbol(f1, Decl(inferTypes1.ts, 14, 124)) +>T14 : Symbol(T14, Decl(inferTypes1.ts, 26, 66)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) +>f1 : Symbol(f1, Decl(inferTypes1.ts, 12, 27)) -type T15 = ReturnType; // C ->T15 : Symbol(T15, Decl(inferTypes1.ts, 29, 33)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) ->C : Symbol(C, Decl(inferTypes1.ts, 18, 1)) +type T15 = ReturnType; // any +>T15 : Symbol(T15, Decl(inferTypes1.ts, 27, 33)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) -type T16 = ReturnType; // any ->T16 : Symbol(T16, Decl(inferTypes1.ts, 30, 32)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) +type T16 = ReturnType; // any +>T16 : Symbol(T16, Decl(inferTypes1.ts, 28, 27)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) -type T17 = ReturnType; // any ->T17 : Symbol(T17, Decl(inferTypes1.ts, 31, 27)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) +type T17 = ReturnType; // Error +>T17 : Symbol(T17, Decl(inferTypes1.ts, 29, 29)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) -type T18 = ReturnType; // Error ->T18 : Symbol(T18, Decl(inferTypes1.ts, 32, 29)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) +type T18 = ReturnType; // Error +>T18 : Symbol(T18, Decl(inferTypes1.ts, 30, 30)) +>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --)) +>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) -type T19 = ReturnType; // any ->T19 : Symbol(T19, Decl(inferTypes1.ts, 33, 30)) ->ReturnType : Symbol(ReturnType, Decl(inferTypes1.ts, 12, 27)) +type U10 = InstanceType; // C +>U10 : Symbol(U10, Decl(inferTypes1.ts, 31, 32)) +>InstanceType : Symbol(InstanceType, Decl(lib.d.ts, --, --)) +>C : Symbol(C, Decl(inferTypes1.ts, 16, 1)) + +type U11 = InstanceType; // any +>U11 : Symbol(U11, Decl(inferTypes1.ts, 33, 34)) +>InstanceType : Symbol(InstanceType, Decl(lib.d.ts, --, --)) + +type U12 = InstanceType; // any +>U12 : Symbol(U12, Decl(inferTypes1.ts, 34, 29)) +>InstanceType : Symbol(InstanceType, Decl(lib.d.ts, --, --)) + +type U13 = InstanceType; // Error +>U13 : Symbol(U13, Decl(inferTypes1.ts, 35, 31)) +>InstanceType : Symbol(InstanceType, Decl(lib.d.ts, --, --)) + +type U14 = InstanceType; // Error +>U14 : Symbol(U14, Decl(inferTypes1.ts, 36, 32)) +>InstanceType : Symbol(InstanceType, Decl(lib.d.ts, --, --)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) type ArgumentType any> = T extends (a: infer A) => any ? A : any; ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) ->T : Symbol(T, Decl(inferTypes1.ts, 36, 18)) ->x : Symbol(x, Decl(inferTypes1.ts, 36, 29)) ->T : Symbol(T, Decl(inferTypes1.ts, 36, 18)) ->a : Symbol(a, Decl(inferTypes1.ts, 36, 58)) ->A : Symbol(A, Decl(inferTypes1.ts, 36, 66)) ->A : Symbol(A, Decl(inferTypes1.ts, 36, 66)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) +>T : Symbol(T, Decl(inferTypes1.ts, 39, 18)) +>x : Symbol(x, Decl(inferTypes1.ts, 39, 29)) +>T : Symbol(T, Decl(inferTypes1.ts, 39, 18)) +>a : Symbol(a, Decl(inferTypes1.ts, 39, 58)) +>A : Symbol(A, Decl(inferTypes1.ts, 39, 66)) +>A : Symbol(A, Decl(inferTypes1.ts, 39, 66)) type T20 = ArgumentType<() => void>; // never ->T20 : Symbol(T20, Decl(inferTypes1.ts, 36, 87)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) +>T20 : Symbol(T20, Decl(inferTypes1.ts, 39, 87)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) type T21 = ArgumentType<(x: string) => number>; // string ->T21 : Symbol(T21, Decl(inferTypes1.ts, 38, 36)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) ->x : Symbol(x, Decl(inferTypes1.ts, 39, 25)) +>T21 : Symbol(T21, Decl(inferTypes1.ts, 41, 36)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) +>x : Symbol(x, Decl(inferTypes1.ts, 42, 25)) type T22 = ArgumentType<(x?: string) => number>; // string | undefined ->T22 : Symbol(T22, Decl(inferTypes1.ts, 39, 47)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) ->x : Symbol(x, Decl(inferTypes1.ts, 40, 25)) +>T22 : Symbol(T22, Decl(inferTypes1.ts, 42, 47)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) +>x : Symbol(x, Decl(inferTypes1.ts, 43, 25)) type T23 = ArgumentType<(...args: string[]) => number>; // string ->T23 : Symbol(T23, Decl(inferTypes1.ts, 40, 48)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) ->args : Symbol(args, Decl(inferTypes1.ts, 41, 25)) +>T23 : Symbol(T23, Decl(inferTypes1.ts, 43, 48)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) +>args : Symbol(args, Decl(inferTypes1.ts, 44, 25)) type T24 = ArgumentType<(x: string, y: string) => number>; // Error ->T24 : Symbol(T24, Decl(inferTypes1.ts, 41, 55)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) ->x : Symbol(x, Decl(inferTypes1.ts, 42, 25)) ->y : Symbol(y, Decl(inferTypes1.ts, 42, 35)) +>T24 : Symbol(T24, Decl(inferTypes1.ts, 44, 55)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) +>x : Symbol(x, Decl(inferTypes1.ts, 45, 25)) +>y : Symbol(y, Decl(inferTypes1.ts, 45, 35)) type T25 = ArgumentType; // Error ->T25 : Symbol(T25, Decl(inferTypes1.ts, 42, 58)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) +>T25 : Symbol(T25, Decl(inferTypes1.ts, 45, 58)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) type T26 = ArgumentType; // any ->T26 : Symbol(T26, Decl(inferTypes1.ts, 43, 34)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) +>T26 : Symbol(T26, Decl(inferTypes1.ts, 46, 34)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) type T27 = ArgumentType; // any ->T27 : Symbol(T27, Decl(inferTypes1.ts, 44, 29)) ->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 34, 32)) +>T27 : Symbol(T27, Decl(inferTypes1.ts, 47, 29)) +>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34)) type X1 = T extends { x: infer X, y: infer Y } ? [X, Y] : any; ->X1 : Symbol(X1, Decl(inferTypes1.ts, 45, 31)) ->T : Symbol(T, Decl(inferTypes1.ts, 47, 8)) ->x : Symbol(x, Decl(inferTypes1.ts, 47, 19)) ->y : Symbol(y, Decl(inferTypes1.ts, 47, 27)) ->T : Symbol(T, Decl(inferTypes1.ts, 47, 8)) ->x : Symbol(x, Decl(inferTypes1.ts, 47, 51)) ->X : Symbol(X, Decl(inferTypes1.ts, 47, 60)) ->y : Symbol(y, Decl(inferTypes1.ts, 47, 63)) ->Y : Symbol(Y, Decl(inferTypes1.ts, 47, 72)) ->X : Symbol(X, Decl(inferTypes1.ts, 47, 60)) ->Y : Symbol(Y, Decl(inferTypes1.ts, 47, 72)) +>X1 : Symbol(X1, Decl(inferTypes1.ts, 48, 31)) +>T : Symbol(T, Decl(inferTypes1.ts, 50, 8)) +>x : Symbol(x, Decl(inferTypes1.ts, 50, 19)) +>y : Symbol(y, Decl(inferTypes1.ts, 50, 27)) +>T : Symbol(T, Decl(inferTypes1.ts, 50, 8)) +>x : Symbol(x, Decl(inferTypes1.ts, 50, 51)) +>X : Symbol(X, Decl(inferTypes1.ts, 50, 60)) +>y : Symbol(y, Decl(inferTypes1.ts, 50, 63)) +>Y : Symbol(Y, Decl(inferTypes1.ts, 50, 72)) +>X : Symbol(X, Decl(inferTypes1.ts, 50, 60)) +>Y : Symbol(Y, Decl(inferTypes1.ts, 50, 72)) type T30 = X1<{ x: any, y: any }>; // [any, any] ->T30 : Symbol(T30, Decl(inferTypes1.ts, 47, 92)) ->X1 : Symbol(X1, Decl(inferTypes1.ts, 45, 31)) ->x : Symbol(x, Decl(inferTypes1.ts, 49, 15)) ->y : Symbol(y, Decl(inferTypes1.ts, 49, 23)) +>T30 : Symbol(T30, Decl(inferTypes1.ts, 50, 92)) +>X1 : Symbol(X1, Decl(inferTypes1.ts, 48, 31)) +>x : Symbol(x, Decl(inferTypes1.ts, 52, 15)) +>y : Symbol(y, Decl(inferTypes1.ts, 52, 23)) type T31 = X1<{ x: number, y: string }>; // [number, string] ->T31 : Symbol(T31, Decl(inferTypes1.ts, 49, 34)) ->X1 : Symbol(X1, Decl(inferTypes1.ts, 45, 31)) ->x : Symbol(x, Decl(inferTypes1.ts, 50, 15)) ->y : Symbol(y, Decl(inferTypes1.ts, 50, 26)) +>T31 : Symbol(T31, Decl(inferTypes1.ts, 52, 34)) +>X1 : Symbol(X1, Decl(inferTypes1.ts, 48, 31)) +>x : Symbol(x, Decl(inferTypes1.ts, 53, 15)) +>y : Symbol(y, Decl(inferTypes1.ts, 53, 26)) type T32 = X1<{ x: number, y: string, z: boolean }>; // [number, string] ->T32 : Symbol(T32, Decl(inferTypes1.ts, 50, 40)) ->X1 : Symbol(X1, Decl(inferTypes1.ts, 45, 31)) ->x : Symbol(x, Decl(inferTypes1.ts, 51, 15)) ->y : Symbol(y, Decl(inferTypes1.ts, 51, 26)) ->z : Symbol(z, Decl(inferTypes1.ts, 51, 37)) +>T32 : Symbol(T32, Decl(inferTypes1.ts, 53, 40)) +>X1 : Symbol(X1, Decl(inferTypes1.ts, 48, 31)) +>x : Symbol(x, Decl(inferTypes1.ts, 54, 15)) +>y : Symbol(y, Decl(inferTypes1.ts, 54, 26)) +>z : Symbol(z, Decl(inferTypes1.ts, 54, 37)) type X2 = T extends { a: infer U, b: infer U } ? U : never; ->X2 : Symbol(X2, Decl(inferTypes1.ts, 51, 52)) ->T : Symbol(T, Decl(inferTypes1.ts, 53, 8)) ->T : Symbol(T, Decl(inferTypes1.ts, 53, 8)) ->a : Symbol(a, Decl(inferTypes1.ts, 53, 24)) ->U : Symbol(U, Decl(inferTypes1.ts, 53, 33), Decl(inferTypes1.ts, 53, 45)) ->b : Symbol(b, Decl(inferTypes1.ts, 53, 36)) ->U : Symbol(U, Decl(inferTypes1.ts, 53, 33), Decl(inferTypes1.ts, 53, 45)) ->U : Symbol(U, Decl(inferTypes1.ts, 53, 33), Decl(inferTypes1.ts, 53, 45)) +>X2 : Symbol(X2, Decl(inferTypes1.ts, 54, 52)) +>T : Symbol(T, Decl(inferTypes1.ts, 56, 8)) +>T : Symbol(T, Decl(inferTypes1.ts, 56, 8)) +>a : Symbol(a, Decl(inferTypes1.ts, 56, 24)) +>U : Symbol(U, Decl(inferTypes1.ts, 56, 33), Decl(inferTypes1.ts, 56, 45)) +>b : Symbol(b, Decl(inferTypes1.ts, 56, 36)) +>U : Symbol(U, Decl(inferTypes1.ts, 56, 33), Decl(inferTypes1.ts, 56, 45)) +>U : Symbol(U, Decl(inferTypes1.ts, 56, 33), Decl(inferTypes1.ts, 56, 45)) type T40 = X2<{}>; // never ->T40 : Symbol(T40, Decl(inferTypes1.ts, 53, 62)) ->X2 : Symbol(X2, Decl(inferTypes1.ts, 51, 52)) +>T40 : Symbol(T40, Decl(inferTypes1.ts, 56, 62)) +>X2 : Symbol(X2, Decl(inferTypes1.ts, 54, 52)) type T41 = X2<{ a: string }>; // never ->T41 : Symbol(T41, Decl(inferTypes1.ts, 55, 18)) ->X2 : Symbol(X2, Decl(inferTypes1.ts, 51, 52)) ->a : Symbol(a, Decl(inferTypes1.ts, 56, 15)) +>T41 : Symbol(T41, Decl(inferTypes1.ts, 58, 18)) +>X2 : Symbol(X2, Decl(inferTypes1.ts, 54, 52)) +>a : Symbol(a, Decl(inferTypes1.ts, 59, 15)) type T42 = X2<{ a: string, b: string }>; // string ->T42 : Symbol(T42, Decl(inferTypes1.ts, 56, 29)) ->X2 : Symbol(X2, Decl(inferTypes1.ts, 51, 52)) ->a : Symbol(a, Decl(inferTypes1.ts, 57, 15)) ->b : Symbol(b, Decl(inferTypes1.ts, 57, 26)) +>T42 : Symbol(T42, Decl(inferTypes1.ts, 59, 29)) +>X2 : Symbol(X2, Decl(inferTypes1.ts, 54, 52)) +>a : Symbol(a, Decl(inferTypes1.ts, 60, 15)) +>b : Symbol(b, Decl(inferTypes1.ts, 60, 26)) type T43 = X2<{ a: number, b: string }>; // string | number ->T43 : Symbol(T43, Decl(inferTypes1.ts, 57, 40)) ->X2 : Symbol(X2, Decl(inferTypes1.ts, 51, 52)) ->a : Symbol(a, Decl(inferTypes1.ts, 58, 15)) ->b : Symbol(b, Decl(inferTypes1.ts, 58, 26)) +>T43 : Symbol(T43, Decl(inferTypes1.ts, 60, 40)) +>X2 : Symbol(X2, Decl(inferTypes1.ts, 54, 52)) +>a : Symbol(a, Decl(inferTypes1.ts, 61, 15)) +>b : Symbol(b, Decl(inferTypes1.ts, 61, 26)) type T44 = X2<{ a: number, b: string, c: boolean }>; // string | number ->T44 : Symbol(T44, Decl(inferTypes1.ts, 58, 40)) ->X2 : Symbol(X2, Decl(inferTypes1.ts, 51, 52)) ->a : Symbol(a, Decl(inferTypes1.ts, 59, 15)) ->b : Symbol(b, Decl(inferTypes1.ts, 59, 26)) ->c : Symbol(c, Decl(inferTypes1.ts, 59, 37)) +>T44 : Symbol(T44, Decl(inferTypes1.ts, 61, 40)) +>X2 : Symbol(X2, Decl(inferTypes1.ts, 54, 52)) +>a : Symbol(a, Decl(inferTypes1.ts, 62, 15)) +>b : Symbol(b, Decl(inferTypes1.ts, 62, 26)) +>c : Symbol(c, Decl(inferTypes1.ts, 62, 37)) type X3 = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never; ->X3 : Symbol(X3, Decl(inferTypes1.ts, 59, 52)) ->T : Symbol(T, Decl(inferTypes1.ts, 61, 8)) ->T : Symbol(T, Decl(inferTypes1.ts, 61, 8)) ->a : Symbol(a, Decl(inferTypes1.ts, 61, 24)) ->x : Symbol(x, Decl(inferTypes1.ts, 61, 29)) ->U : Symbol(U, Decl(inferTypes1.ts, 61, 37), Decl(inferTypes1.ts, 61, 62)) ->b : Symbol(b, Decl(inferTypes1.ts, 61, 49)) ->x : Symbol(x, Decl(inferTypes1.ts, 61, 54)) ->U : Symbol(U, Decl(inferTypes1.ts, 61, 37), Decl(inferTypes1.ts, 61, 62)) ->U : Symbol(U, Decl(inferTypes1.ts, 61, 37), Decl(inferTypes1.ts, 61, 62)) +>X3 : Symbol(X3, Decl(inferTypes1.ts, 62, 52)) +>T : Symbol(T, Decl(inferTypes1.ts, 64, 8)) +>T : Symbol(T, Decl(inferTypes1.ts, 64, 8)) +>a : Symbol(a, Decl(inferTypes1.ts, 64, 24)) +>x : Symbol(x, Decl(inferTypes1.ts, 64, 29)) +>U : Symbol(U, Decl(inferTypes1.ts, 64, 37), Decl(inferTypes1.ts, 64, 62)) +>b : Symbol(b, Decl(inferTypes1.ts, 64, 49)) +>x : Symbol(x, Decl(inferTypes1.ts, 64, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 64, 37), Decl(inferTypes1.ts, 64, 62)) +>U : Symbol(U, Decl(inferTypes1.ts, 64, 37), Decl(inferTypes1.ts, 64, 62)) type T50 = X3<{}>; // never ->T50 : Symbol(T50, Decl(inferTypes1.ts, 61, 88)) ->X3 : Symbol(X3, Decl(inferTypes1.ts, 59, 52)) +>T50 : Symbol(T50, Decl(inferTypes1.ts, 64, 88)) +>X3 : Symbol(X3, Decl(inferTypes1.ts, 62, 52)) type T51 = X3<{ a: (x: string) => void }>; // never ->T51 : Symbol(T51, Decl(inferTypes1.ts, 63, 18)) ->X3 : Symbol(X3, Decl(inferTypes1.ts, 59, 52)) ->a : Symbol(a, Decl(inferTypes1.ts, 64, 15)) ->x : Symbol(x, Decl(inferTypes1.ts, 64, 20)) - -type T52 = X3<{ a: (x: string) => void, b: (x: string) => void }>; // string ->T52 : Symbol(T52, Decl(inferTypes1.ts, 64, 42)) ->X3 : Symbol(X3, Decl(inferTypes1.ts, 59, 52)) ->a : Symbol(a, Decl(inferTypes1.ts, 65, 15)) ->x : Symbol(x, Decl(inferTypes1.ts, 65, 20)) ->b : Symbol(b, Decl(inferTypes1.ts, 65, 39)) ->x : Symbol(x, Decl(inferTypes1.ts, 65, 44)) - -type T53 = X3<{ a: (x: number) => void, b: (x: string) => void }>; // string & number ->T53 : Symbol(T53, Decl(inferTypes1.ts, 65, 66)) ->X3 : Symbol(X3, Decl(inferTypes1.ts, 59, 52)) ->a : Symbol(a, Decl(inferTypes1.ts, 66, 15)) ->x : Symbol(x, Decl(inferTypes1.ts, 66, 20)) ->b : Symbol(b, Decl(inferTypes1.ts, 66, 39)) ->x : Symbol(x, Decl(inferTypes1.ts, 66, 44)) - -type T54 = X3<{ a: (x: number) => void, b: () => void }>; // number ->T54 : Symbol(T54, Decl(inferTypes1.ts, 66, 66)) ->X3 : Symbol(X3, Decl(inferTypes1.ts, 59, 52)) +>T51 : Symbol(T51, Decl(inferTypes1.ts, 66, 18)) +>X3 : Symbol(X3, Decl(inferTypes1.ts, 62, 52)) >a : Symbol(a, Decl(inferTypes1.ts, 67, 15)) >x : Symbol(x, Decl(inferTypes1.ts, 67, 20)) ->b : Symbol(b, Decl(inferTypes1.ts, 67, 39)) + +type T52 = X3<{ a: (x: string) => void, b: (x: string) => void }>; // string +>T52 : Symbol(T52, Decl(inferTypes1.ts, 67, 42)) +>X3 : Symbol(X3, Decl(inferTypes1.ts, 62, 52)) +>a : Symbol(a, Decl(inferTypes1.ts, 68, 15)) +>x : Symbol(x, Decl(inferTypes1.ts, 68, 20)) +>b : Symbol(b, Decl(inferTypes1.ts, 68, 39)) +>x : Symbol(x, Decl(inferTypes1.ts, 68, 44)) + +type T53 = X3<{ a: (x: number) => void, b: (x: string) => void }>; // string & number +>T53 : Symbol(T53, Decl(inferTypes1.ts, 68, 66)) +>X3 : Symbol(X3, Decl(inferTypes1.ts, 62, 52)) +>a : Symbol(a, Decl(inferTypes1.ts, 69, 15)) +>x : Symbol(x, Decl(inferTypes1.ts, 69, 20)) +>b : Symbol(b, Decl(inferTypes1.ts, 69, 39)) +>x : Symbol(x, Decl(inferTypes1.ts, 69, 44)) + +type T54 = X3<{ a: (x: number) => void, b: () => void }>; // number +>T54 : Symbol(T54, Decl(inferTypes1.ts, 69, 66)) +>X3 : Symbol(X3, Decl(inferTypes1.ts, 62, 52)) +>a : Symbol(a, Decl(inferTypes1.ts, 70, 15)) +>x : Symbol(x, Decl(inferTypes1.ts, 70, 20)) +>b : Symbol(b, Decl(inferTypes1.ts, 70, 39)) type T60 = infer U; // Error ->T60 : Symbol(T60, Decl(inferTypes1.ts, 67, 57)) ->U : Symbol(U, Decl(inferTypes1.ts, 69, 16)) +>T60 : Symbol(T60, Decl(inferTypes1.ts, 70, 57)) +>U : Symbol(U, Decl(inferTypes1.ts, 72, 16)) type T61 = infer A extends infer B ? infer C : infer D; // Error ->T61 : Symbol(T61, Decl(inferTypes1.ts, 69, 19)) ->T : Symbol(T, Decl(inferTypes1.ts, 70, 9)) ->A : Symbol(A, Decl(inferTypes1.ts, 70, 19)) ->B : Symbol(B, Decl(inferTypes1.ts, 70, 35)) ->C : Symbol(C, Decl(inferTypes1.ts, 70, 45)) ->D : Symbol(D, Decl(inferTypes1.ts, 70, 55)) +>T61 : Symbol(T61, Decl(inferTypes1.ts, 72, 19)) +>T : Symbol(T, Decl(inferTypes1.ts, 73, 9)) +>A : Symbol(A, Decl(inferTypes1.ts, 73, 19)) +>B : Symbol(B, Decl(inferTypes1.ts, 73, 35)) +>C : Symbol(C, Decl(inferTypes1.ts, 73, 45)) +>D : Symbol(D, Decl(inferTypes1.ts, 73, 55)) type T62 = U extends (infer U)[] ? U : U; // Error ->T62 : Symbol(T62, Decl(inferTypes1.ts, 70, 58)) ->T : Symbol(T, Decl(inferTypes1.ts, 71, 9)) ->U : Symbol(U, Decl(inferTypes1.ts, 71, 30)) ->U : Symbol(U, Decl(inferTypes1.ts, 71, 30)) +>T62 : Symbol(T62, Decl(inferTypes1.ts, 73, 58)) +>T : Symbol(T, Decl(inferTypes1.ts, 74, 9)) +>U : Symbol(U, Decl(inferTypes1.ts, 74, 30)) +>U : Symbol(U, Decl(inferTypes1.ts, 74, 30)) type T70 = { x: T }; ->T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) ->T : Symbol(T, Decl(inferTypes1.ts, 73, 9)) ->x : Symbol(x, Decl(inferTypes1.ts, 73, 30)) ->T : Symbol(T, Decl(inferTypes1.ts, 73, 9)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 74, 44)) +>T : Symbol(T, Decl(inferTypes1.ts, 76, 9)) +>x : Symbol(x, Decl(inferTypes1.ts, 76, 30)) +>T : Symbol(T, Decl(inferTypes1.ts, 76, 9)) type T71 = T extends T70 ? T70 : never; ->T71 : Symbol(T71, Decl(inferTypes1.ts, 73, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 74, 9)) ->T : Symbol(T, Decl(inferTypes1.ts, 74, 9)) ->T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) ->U : Symbol(U, Decl(inferTypes1.ts, 74, 33)) ->T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) ->U : Symbol(U, Decl(inferTypes1.ts, 74, 33)) +>T71 : Symbol(T71, Decl(inferTypes1.ts, 76, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 77, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 77, 9)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 74, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 77, 33)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 74, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 77, 33)) type T72 = { y: T }; ->T72 : Symbol(T72, Decl(inferTypes1.ts, 74, 54)) ->T : Symbol(T, Decl(inferTypes1.ts, 76, 9)) ->y : Symbol(y, Decl(inferTypes1.ts, 76, 30)) ->T : Symbol(T, Decl(inferTypes1.ts, 76, 9)) +>T72 : Symbol(T72, Decl(inferTypes1.ts, 77, 54)) +>T : Symbol(T, Decl(inferTypes1.ts, 79, 9)) +>y : Symbol(y, Decl(inferTypes1.ts, 79, 30)) +>T : Symbol(T, Decl(inferTypes1.ts, 79, 9)) type T73 = T extends T72 ? T70 : never; // Error ->T73 : Symbol(T73, Decl(inferTypes1.ts, 76, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 77, 9)) ->T : Symbol(T, Decl(inferTypes1.ts, 77, 9)) ->T72 : Symbol(T72, Decl(inferTypes1.ts, 74, 54)) ->U : Symbol(U, Decl(inferTypes1.ts, 77, 33)) ->T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) ->U : Symbol(U, Decl(inferTypes1.ts, 77, 33)) +>T73 : Symbol(T73, Decl(inferTypes1.ts, 79, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 80, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 80, 9)) +>T72 : Symbol(T72, Decl(inferTypes1.ts, 77, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 74, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33)) type T74 = { x: T, y: U }; ->T74 : Symbol(T74, Decl(inferTypes1.ts, 77, 54)) ->T : Symbol(T, Decl(inferTypes1.ts, 79, 9)) ->U : Symbol(U, Decl(inferTypes1.ts, 79, 26)) ->x : Symbol(x, Decl(inferTypes1.ts, 79, 48)) ->T : Symbol(T, Decl(inferTypes1.ts, 79, 9)) ->y : Symbol(y, Decl(inferTypes1.ts, 79, 54)) ->U : Symbol(U, Decl(inferTypes1.ts, 79, 26)) +>T74 : Symbol(T74, Decl(inferTypes1.ts, 80, 54)) +>T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) +>U : Symbol(U, Decl(inferTypes1.ts, 82, 26)) +>x : Symbol(x, Decl(inferTypes1.ts, 82, 48)) +>T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) +>y : Symbol(y, Decl(inferTypes1.ts, 82, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 82, 26)) type T75 = T extends T74 ? T70 | T72 | T74 : never; ->T75 : Symbol(T75, Decl(inferTypes1.ts, 79, 62)) ->T : Symbol(T, Decl(inferTypes1.ts, 80, 9)) ->T : Symbol(T, Decl(inferTypes1.ts, 80, 9)) ->T74 : Symbol(T74, Decl(inferTypes1.ts, 77, 54)) ->U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) ->U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) ->T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) ->U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) ->T72 : Symbol(T72, Decl(inferTypes1.ts, 74, 54)) ->U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) ->T74 : Symbol(T74, Decl(inferTypes1.ts, 77, 54)) ->U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) ->U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) +>T75 : Symbol(T75, Decl(inferTypes1.ts, 82, 62)) +>T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) +>T74 : Symbol(T74, Decl(inferTypes1.ts, 80, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 83, 33), Decl(inferTypes1.ts, 83, 42)) +>U : Symbol(U, Decl(inferTypes1.ts, 83, 33), Decl(inferTypes1.ts, 83, 42)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 74, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 83, 33), Decl(inferTypes1.ts, 83, 42)) +>T72 : Symbol(T72, Decl(inferTypes1.ts, 77, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 83, 33), Decl(inferTypes1.ts, 83, 42)) +>T74 : Symbol(T74, Decl(inferTypes1.ts, 80, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 83, 33), Decl(inferTypes1.ts, 83, 42)) +>U : Symbol(U, Decl(inferTypes1.ts, 83, 33), Decl(inferTypes1.ts, 83, 42)) type T76 = { x: T }; ->T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) ->T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) ->T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) ->U : Symbol(U, Decl(inferTypes1.ts, 82, 23)) ->T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) ->x : Symbol(x, Decl(inferTypes1.ts, 82, 40)) ->T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 83, 84)) +>T : Symbol(T, Decl(inferTypes1.ts, 85, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 85, 9)) +>U : Symbol(U, Decl(inferTypes1.ts, 85, 23)) +>T : Symbol(T, Decl(inferTypes1.ts, 85, 9)) +>x : Symbol(x, Decl(inferTypes1.ts, 85, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 85, 9)) type T77 = T extends T76 ? T76 : never; ->T77 : Symbol(T77, Decl(inferTypes1.ts, 82, 48)) ->T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) ->T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) ->T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) ->X : Symbol(X, Decl(inferTypes1.ts, 83, 33)) ->Y : Symbol(Y, Decl(inferTypes1.ts, 83, 42)) ->T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) ->X : Symbol(X, Decl(inferTypes1.ts, 83, 33)) ->Y : Symbol(Y, Decl(inferTypes1.ts, 83, 42)) +>T77 : Symbol(T77, Decl(inferTypes1.ts, 85, 48)) +>T : Symbol(T, Decl(inferTypes1.ts, 86, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 86, 9)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 83, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 86, 33)) +>Y : Symbol(Y, Decl(inferTypes1.ts, 86, 42)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 83, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 86, 33)) +>Y : Symbol(Y, Decl(inferTypes1.ts, 86, 42)) type T78 = T extends T76 ? T76 : never; ->T78 : Symbol(T78, Decl(inferTypes1.ts, 83, 66)) ->T : Symbol(T, Decl(inferTypes1.ts, 84, 9)) ->T : Symbol(T, Decl(inferTypes1.ts, 84, 9)) ->T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) ->X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) ->X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) ->T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) ->X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) ->X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) +>T78 : Symbol(T78, Decl(inferTypes1.ts, 86, 66)) +>T : Symbol(T, Decl(inferTypes1.ts, 87, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 87, 9)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 83, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 87, 33), Decl(inferTypes1.ts, 87, 42)) +>X : Symbol(X, Decl(inferTypes1.ts, 87, 33), Decl(inferTypes1.ts, 87, 42)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 83, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 87, 33), Decl(inferTypes1.ts, 87, 42)) +>X : Symbol(X, Decl(inferTypes1.ts, 87, 33), Decl(inferTypes1.ts, 87, 42)) // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified }; ->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 84, 66)) ->T : Symbol(T, Decl(inferTypes1.ts, 88, 21)) ->K : Symbol(K, Decl(inferTypes1.ts, 88, 44)) ->T : Symbol(T, Decl(inferTypes1.ts, 88, 21)) ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 88, 77)) ->T : Symbol(T, Decl(inferTypes1.ts, 88, 21)) ->K : Symbol(K, Decl(inferTypes1.ts, 88, 44)) +>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 87, 66)) +>T : Symbol(T, Decl(inferTypes1.ts, 91, 21)) +>K : Symbol(K, Decl(inferTypes1.ts, 91, 44)) +>T : Symbol(T, Decl(inferTypes1.ts, 91, 21)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 91, 77)) +>T : Symbol(T, Decl(inferTypes1.ts, 91, 21)) +>K : Symbol(K, Decl(inferTypes1.ts, 91, 44)) type Jsonified = ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 88, 77)) ->T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 91, 77)) +>T : Symbol(T, Decl(inferTypes1.ts, 93, 15)) T extends string | number | boolean | null ? T ->T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) ->T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 93, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 93, 15)) : T extends undefined | Function ? never // undefined and functions are removed ->T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 93, 15)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) : T extends { toJSON(): infer R } ? R // toJSON is called if it exists (e.g. Date) ->T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) ->toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 93, 17)) ->R : Symbol(R, Decl(inferTypes1.ts, 93, 33)) ->R : Symbol(R, Decl(inferTypes1.ts, 93, 33)) +>T : Symbol(T, Decl(inferTypes1.ts, 93, 15)) +>toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 96, 17)) +>R : Symbol(R, Decl(inferTypes1.ts, 96, 33)) +>R : Symbol(R, Decl(inferTypes1.ts, 96, 33)) : T extends object ? JsonifiedObject ->T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) ->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 84, 66)) ->T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 93, 15)) +>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 87, 66)) +>T : Symbol(T, Decl(inferTypes1.ts, 93, 15)) : "what is this"; type Example = { ->Example : Symbol(Example, Decl(inferTypes1.ts, 95, 21)) +>Example : Symbol(Example, Decl(inferTypes1.ts, 98, 21)) str: "literalstring", ->str : Symbol(str, Decl(inferTypes1.ts, 97, 16)) +>str : Symbol(str, Decl(inferTypes1.ts, 100, 16)) fn: () => void, ->fn : Symbol(fn, Decl(inferTypes1.ts, 98, 25)) +>fn : Symbol(fn, Decl(inferTypes1.ts, 101, 25)) date: Date, ->date : Symbol(date, Decl(inferTypes1.ts, 99, 19)) +>date : Symbol(date, Decl(inferTypes1.ts, 102, 19)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) customClass: MyClass, ->customClass : Symbol(customClass, Decl(inferTypes1.ts, 100, 15)) ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 107, 1)) +>customClass : Symbol(customClass, Decl(inferTypes1.ts, 103, 15)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 110, 1)) obj: { ->obj : Symbol(obj, Decl(inferTypes1.ts, 101, 25)) +>obj : Symbol(obj, Decl(inferTypes1.ts, 104, 25)) prop: "property", ->prop : Symbol(prop, Decl(inferTypes1.ts, 102, 10)) +>prop : Symbol(prop, Decl(inferTypes1.ts, 105, 10)) clz: MyClass, ->clz : Symbol(clz, Decl(inferTypes1.ts, 103, 25)) ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 107, 1)) +>clz : Symbol(clz, Decl(inferTypes1.ts, 106, 25)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 110, 1)) nested: { attr: Date } ->nested : Symbol(nested, Decl(inferTypes1.ts, 104, 21)) ->attr : Symbol(attr, Decl(inferTypes1.ts, 105, 17)) +>nested : Symbol(nested, Decl(inferTypes1.ts, 107, 21)) +>attr : Symbol(attr, Decl(inferTypes1.ts, 108, 17)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) }, } declare class MyClass { ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 107, 1)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 110, 1)) toJSON(): "correct"; ->toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 109, 23)) +>toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 112, 23)) } type JsonifiedExample = Jsonified; ->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 111, 1)) ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 88, 77)) ->Example : Symbol(Example, Decl(inferTypes1.ts, 95, 21)) +>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 114, 1)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 91, 77)) +>Example : Symbol(Example, Decl(inferTypes1.ts, 98, 21)) declare let ex: JsonifiedExample; ->ex : Symbol(ex, Decl(inferTypes1.ts, 114, 11)) ->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 111, 1)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 117, 11)) +>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 114, 1)) const z1: "correct" = ex.customClass; ->z1 : Symbol(z1, Decl(inferTypes1.ts, 115, 5)) ->ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 100, 15)) ->ex : Symbol(ex, Decl(inferTypes1.ts, 114, 11)) ->customClass : Symbol(customClass, Decl(inferTypes1.ts, 100, 15)) +>z1 : Symbol(z1, Decl(inferTypes1.ts, 118, 5)) +>ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 103, 15)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 117, 11)) +>customClass : Symbol(customClass, Decl(inferTypes1.ts, 103, 15)) const z2: string = ex.obj.nested.attr; ->z2 : Symbol(z2, Decl(inferTypes1.ts, 116, 5)) ->ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 105, 17)) ->ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 104, 21)) ->ex.obj : Symbol(obj, Decl(inferTypes1.ts, 101, 25)) ->ex : Symbol(ex, Decl(inferTypes1.ts, 114, 11)) ->obj : Symbol(obj, Decl(inferTypes1.ts, 101, 25)) ->nested : Symbol(nested, Decl(inferTypes1.ts, 104, 21)) ->attr : Symbol(attr, Decl(inferTypes1.ts, 105, 17)) +>z2 : Symbol(z2, Decl(inferTypes1.ts, 119, 5)) +>ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 108, 17)) +>ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 107, 21)) +>ex.obj : Symbol(obj, Decl(inferTypes1.ts, 104, 25)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 117, 11)) +>obj : Symbol(obj, Decl(inferTypes1.ts, 104, 25)) +>nested : Symbol(nested, Decl(inferTypes1.ts, 107, 21)) +>attr : Symbol(attr, Decl(inferTypes1.ts, 108, 17)) // Repros from #21631 type A1> = [T, U]; ->A1 : Symbol(A1, Decl(inferTypes1.ts, 116, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 120, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 120, 10)) ->A1 : Symbol(A1, Decl(inferTypes1.ts, 116, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 120, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 120, 10)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 119, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 123, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 123, 10)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 119, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 123, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 123, 10)) type B1 = S extends A1 ? [T, U] : never; ->B1 : Symbol(B1, Decl(inferTypes1.ts, 120, 44)) ->S : Symbol(S, Decl(inferTypes1.ts, 121, 8)) ->S : Symbol(S, Decl(inferTypes1.ts, 121, 8)) ->A1 : Symbol(A1, Decl(inferTypes1.ts, 116, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 121, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 121, 40)) ->T : Symbol(T, Decl(inferTypes1.ts, 121, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 121, 40)) +>B1 : Symbol(B1, Decl(inferTypes1.ts, 123, 44)) +>S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) +>S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 119, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 124, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 124, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 124, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 124, 40)) type A2 = [T, U]; ->A2 : Symbol(A2, Decl(inferTypes1.ts, 121, 61)) ->T : Symbol(T, Decl(inferTypes1.ts, 123, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 123, 10)) ->T : Symbol(T, Decl(inferTypes1.ts, 123, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 123, 10)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 124, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 126, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 126, 10)) +>T : Symbol(T, Decl(inferTypes1.ts, 126, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 126, 10)) type B2 = S extends A2 ? [T, U] : never; ->B2 : Symbol(B2, Decl(inferTypes1.ts, 123, 36)) ->S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) ->S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) ->A2 : Symbol(A2, Decl(inferTypes1.ts, 121, 61)) ->T : Symbol(T, Decl(inferTypes1.ts, 124, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 124, 40)) ->T : Symbol(T, Decl(inferTypes1.ts, 124, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 124, 40)) +>B2 : Symbol(B2, Decl(inferTypes1.ts, 126, 36)) +>S : Symbol(S, Decl(inferTypes1.ts, 127, 8)) +>S : Symbol(S, Decl(inferTypes1.ts, 127, 8)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 124, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 127, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 127, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 127, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 127, 40)) type C2 = S extends A2 ? [T, U] : never; ->C2 : Symbol(C2, Decl(inferTypes1.ts, 124, 61)) ->S : Symbol(S, Decl(inferTypes1.ts, 125, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 125, 10)) ->S : Symbol(S, Decl(inferTypes1.ts, 125, 8)) ->A2 : Symbol(A2, Decl(inferTypes1.ts, 121, 61)) ->T : Symbol(T, Decl(inferTypes1.ts, 125, 47)) ->U : Symbol(U, Decl(inferTypes1.ts, 125, 10)) ->T : Symbol(T, Decl(inferTypes1.ts, 125, 47)) ->U : Symbol(U, Decl(inferTypes1.ts, 125, 10)) +>C2 : Symbol(C2, Decl(inferTypes1.ts, 127, 61)) +>S : Symbol(S, Decl(inferTypes1.ts, 128, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 128, 10)) +>S : Symbol(S, Decl(inferTypes1.ts, 128, 8)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 124, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 128, 47)) +>U : Symbol(U, Decl(inferTypes1.ts, 128, 10)) +>T : Symbol(T, Decl(inferTypes1.ts, 128, 47)) +>U : Symbol(U, Decl(inferTypes1.ts, 128, 10)) // Repro from #21735 type A = T extends string ? { [P in T]: void; } : T; ->A : Symbol(A, Decl(inferTypes1.ts, 125, 71)) ->T : Symbol(T, Decl(inferTypes1.ts, 129, 7)) ->T : Symbol(T, Decl(inferTypes1.ts, 129, 7)) ->P : Symbol(P, Decl(inferTypes1.ts, 129, 34)) ->T : Symbol(T, Decl(inferTypes1.ts, 129, 7)) ->T : Symbol(T, Decl(inferTypes1.ts, 129, 7)) +>A : Symbol(A, Decl(inferTypes1.ts, 128, 71)) +>T : Symbol(T, Decl(inferTypes1.ts, 132, 7)) +>T : Symbol(T, Decl(inferTypes1.ts, 132, 7)) +>P : Symbol(P, Decl(inferTypes1.ts, 132, 34)) +>T : Symbol(T, Decl(inferTypes1.ts, 132, 7)) +>T : Symbol(T, Decl(inferTypes1.ts, 132, 7)) type B = string extends T ? { [P in T]: void; } : T; // Error ->B : Symbol(B, Decl(inferTypes1.ts, 129, 55)) ->T : Symbol(T, Decl(inferTypes1.ts, 130, 7)) ->T : Symbol(T, Decl(inferTypes1.ts, 130, 7)) ->P : Symbol(P, Decl(inferTypes1.ts, 130, 34)) ->T : Symbol(T, Decl(inferTypes1.ts, 130, 7)) ->T : Symbol(T, Decl(inferTypes1.ts, 130, 7)) +>B : Symbol(B, Decl(inferTypes1.ts, 132, 55)) +>T : Symbol(T, Decl(inferTypes1.ts, 133, 7)) +>T : Symbol(T, Decl(inferTypes1.ts, 133, 7)) +>P : Symbol(P, Decl(inferTypes1.ts, 133, 34)) +>T : Symbol(T, Decl(inferTypes1.ts, 133, 7)) +>T : Symbol(T, Decl(inferTypes1.ts, 133, 7)) diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types index 141a3d0aac6..f29c380a0ad 100644 --- a/tests/baselines/reference/inferTypes1.types +++ b/tests/baselines/reference/inferTypes1.types @@ -54,17 +54,6 @@ type T06 = Unpacked; // never >T06 : never >Unpacked : Unpacked -type ReturnType = T extends ((...args: any[]) => infer R) | (new (...args: any[]) => infer R) ? R : any; ->ReturnType : ReturnType ->T : T ->Function : Function ->T : T ->args : any[] ->R : R ->args : any[] ->R : R ->R : R - function f1(s: string) { >f1 : (s: string) => { a: number; b: string; } >s : string @@ -117,26 +106,43 @@ type T14 = ReturnType; // { a: number, b: string } >ReturnType : ReturnType >f1 : (s: string) => { a: number; b: string; } -type T15 = ReturnType; // C ->T15 : C +type T15 = ReturnType; // any +>T15 : any >ReturnType : ReturnType ->C : typeof C -type T16 = ReturnType; // any +type T16 = ReturnType; // any >T16 : any >ReturnType : ReturnType -type T17 = ReturnType; // any +type T17 = ReturnType; // Error >T17 : any >ReturnType : ReturnType -type T18 = ReturnType; // Error +type T18 = ReturnType; // Error >T18 : any >ReturnType : ReturnType +>Function : Function -type T19 = ReturnType; // any ->T19 : any ->ReturnType : ReturnType +type U10 = InstanceType; // C +>U10 : C +>InstanceType : InstanceType +>C : typeof C + +type U11 = InstanceType; // any +>U11 : any +>InstanceType : InstanceType + +type U12 = InstanceType; // any +>U12 : any +>InstanceType : InstanceType + +type U13 = InstanceType; // Error +>U13 : any +>InstanceType : InstanceType + +type U14 = InstanceType; // Error +>U14 : any +>InstanceType : InstanceType >Function : Function type ArgumentType any> = T extends (a: infer A) => any ? A : any; From 425a4182a3eb694835841ea2f614b2a914a348c2 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 9 Feb 2018 14:46:57 -0800 Subject: [PATCH 31/32] Handle empty declaration list in Convert to ES6 Module (#21843) * Handle empty declaration list in Convert to ES6 Module * Fix test --- src/services/refactors/convertToEs6Module.ts | 4 ++-- ...efactorConvertToEs6Module_triggers_declarationList.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/refactorConvertToEs6Module_triggers_declarationList.ts diff --git a/src/services/refactors/convertToEs6Module.ts b/src/services/refactors/convertToEs6Module.ts index 5a7f2e90718..65f9f58ccc4 100644 --- a/src/services/refactors/convertToEs6Module.ts +++ b/src/services/refactors/convertToEs6Module.ts @@ -33,8 +33,8 @@ namespace ts.refactor { return isExportsOrModuleExportsOrAlias(sourceFile, node as PropertyAccessExpression) || isExportsOrModuleExportsOrAlias(sourceFile, (node as PropertyAccessExpression).expression); case SyntaxKind.VariableDeclarationList: - const decl = (node as VariableDeclarationList).declarations[0]; - return isExportsOrModuleExportsOrAlias(sourceFile, decl.initializer); + const decl = firstOrUndefined((node as VariableDeclarationList).declarations); + return !!decl && isExportsOrModuleExportsOrAlias(sourceFile, decl.initializer); case SyntaxKind.VariableDeclaration: return isExportsOrModuleExportsOrAlias(sourceFile, (node as VariableDeclaration).initializer); default: diff --git a/tests/cases/fourslash/refactorConvertToEs6Module_triggers_declarationList.ts b/tests/cases/fourslash/refactorConvertToEs6Module_triggers_declarationList.ts new file mode 100644 index 00000000000..36ec32b0561 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToEs6Module_triggers_declarationList.ts @@ -0,0 +1,9 @@ +/// + +// @allowJs: true + +// @Filename: /a.js +////c[|o|]nst; +////require("x"); + +goTo.eachRange(() => verify.not.refactorAvailable("Convert to ES6 module")); From 49e78f68d2b429f2fe4066d50e2ff212db2c3ca1 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 9 Feb 2018 15:10:34 -0800 Subject: [PATCH 32/32] findAllRefs: Fix bug for `export` not at top-level of a module/namespace (#21846) --- src/services/importTracker.ts | 4 +++- tests/cases/fourslash/findAllRefsExportNotAtTopLevel.ts | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/findAllRefsExportNotAtTopLevel.ts diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index e76e21b2963..d3e57b124de 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -606,7 +606,9 @@ namespace ts.FindAllReferences { } export function getExportInfo(exportSymbol: Symbol, exportKind: ExportKind, checker: TypeChecker): ExportInfo | undefined { - const exportingModuleSymbol = checker.getMergedSymbol(exportSymbol.parent); // Need to get merged symbol in case there's an augmentation. + const moduleSymbol = exportSymbol.parent; + if (!moduleSymbol) return undefined; // This can happen if an `export` is not at the top-level (which is a compile error). + const exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); // Need to get merged symbol in case there's an augmentation. // `export` may appear in a namespace. In that case, just rely on global search. return isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; } diff --git a/tests/cases/fourslash/findAllRefsExportNotAtTopLevel.ts b/tests/cases/fourslash/findAllRefsExportNotAtTopLevel.ts new file mode 100644 index 00000000000..7f9c258bbe2 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsExportNotAtTopLevel.ts @@ -0,0 +1,8 @@ +/// + +////{ +//// export const [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 0; +//// [|x|]; +////} + +verify.singleReferenceGroup("const x: 0");