Merge remote-tracking branch 'origin/main' into release-7.1

This commit is contained in:
typescript-automation[bot] committed 2026-10-19 20:38:54 +00:00
commit 3e9236361f
479 files changed
+17066 -94

No files matched your search

+3 -3
View File
@@ -2,11 +2,11 @@ name: CI
on:
push:
branches: [main, main-ts7, ts7-release, 'release-*']
branches: [main, main-ts7, ts7-release, 'release-*', 'weswigham/*']
pull_request:
branches: [main, main-ts7, ts7-release, 'release-*']
branches: [main, main-ts7, ts7-release, 'release-*', 'weswigham/*']
merge_group:
branches: [main, main-ts7, ts7-release, 'release-*']
branches: [main, main-ts7, ts7-release, 'release-*', 'weswigham/*']
permissions:
contents: read
+2 -2
View File
@@ -838,8 +838,8 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
*
* Fetching the snapshot issues a lightweight request to the server to
* retrieve its timing collection. Collection must be enabled via the
* `collectTiming` option; when it is not, the returned snapshot has
* `enabled: false` and zeroed totals.
* `collectTiming` option or `TS_API_TIMING_DIR` environment variable; when
* it is not, the returned snapshot has `enabled: false` and zeroed totals.
*/
getTimingInfo(): Promise<TimingInfo> {
return this.client.getTimingInfo();
+53 -20
View File
@@ -43,6 +43,7 @@ import {
TimingCollector,
type TimingInfo,
} from "../timing.ts";
import { TimingDump } from "../timingDump.ts";
export type { ClientOptions, ClientSocketOptions, ClientSpawnOptions };
@@ -59,16 +60,22 @@ export class Client {
private closed = false;
private connecting: Promise<void> | undefined;
private timing: TimingCollector | undefined;
private timingDump: TimingDump | undefined;
private closing: Promise<void> | undefined;
private batchedRequests: { method: APIRequest["method"]; params: APIRequest["params"]; resolve: (value: unknown) => void; reject: (reason?: any) => void; }[] = [];
private nextBatch: NodeJS.Immediate | "manual" | undefined;
constructor(options: ClientOptions) {
this.timingDump = TimingDump.fromEnvironment("async", isSpawnOptions(options) ? "spawn" : "socket");
if (this.timingDump || isSpawnOptions(options) && options.collectTiming) {
this.timing = new TimingCollector();
}
if (this.timingDump && isSpawnOptions(options)) {
options = { ...options, collectTiming: true };
}
this.options = options;
if (isSpawnOptions(options)) {
configureFileSystemCallbacks(options.fs);
if (options.collectTiming) {
this.timing = new TimingCollector();
}
}
}
@@ -401,26 +408,52 @@ export class Client {
return this.connection.sendRequest(requestType, undefined);
}
async close(): Promise<void> {
close(): Promise<void> {
return this.closing ??= this.closeWorker();
}
private async closeWorker(): Promise<void> {
await this.connecting?.catch(() => {}); // if connection is still in-progress, wait for it to finish before closing the connection
this.closed = true;
if (this.connection) {
this.connection.dispose();
this.connection = undefined;
try {
if (this.timingDump && this.timing) {
const local = this.timing.getInfo();
let server: ServerTimingInfo | undefined;
let serverTimingError: string | undefined;
const connection = this.connection;
// Closing alone does not reject pending JSON-RPC requests.
const onClose = connection?.onClose(() => connection.dispose());
try {
if (this.connected) server = await this.fetchServerTiming();
}
catch (error) {
serverTimingError = String(error);
}
finally {
onClose?.dispose();
}
this.timingDump.write(local, server, serverTimingError);
}
}
if (this.socket) {
this.socket.destroy();
this.socket = undefined;
finally {
if (this.connection) {
this.connection.dispose();
this.connection = undefined;
}
if (this.socket) {
this.socket.destroy();
this.socket = undefined;
}
if (this.process) {
// Close stdin to unblock the server's read loop, allowing it to exit cleanly.
// The server is blocked on stdin.Read(), so just sending SIGTERM would deadlock:
// - Node won't exit while child is alive
// - Child can't process SIGTERM while blocked on read
// - Read won't error until stdin is closed
this.process.stdin?.end();
this.process = undefined;
}
this.connected = false;
}
if (this.process) {
// Close stdin to unblock the server's read loop, allowing it to exit cleanly.
// The server is blocked on stdin.Read(), so just sending SIGTERM would deadlock:
// - Node won't exit while child is alive
// - Child can't process SIGTERM while blocked on read
// - Read won't error until stdin is closed
this.process.stdin?.end();
this.process = undefined;
}
this.connected = false;
}
}
+3
View File
@@ -33,6 +33,9 @@ export interface ClientSpawnOptions {
* measures its own per-request processing time; both are combined (along
* with an estimated transport overhead) in the snapshot returned by
* {@link API.getTimingInfo}.
* Setting `TS_API_TIMING_DIR` to a nonempty output directory also enables
* collection, even when this option is false, and writes a JSON snapshot
* when the API is closed.
*/
collectTiming?: boolean | undefined;
}
+2 -2
View File
@@ -1343,8 +1343,8 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
*
* Fetching the snapshot issues a lightweight request to the server to
* retrieve its timing collection. Collection must be enabled via the
* `collectTiming` option; when it is not, the returned snapshot has
* `enabled: false` and zeroed totals.
* `collectTiming` option or `TS_API_TIMING_DIR` environment variable; when
* it is not, the returned snapshot has `enabled: false` and zeroed totals.
*/
get getTimingInfo(): {
(): TimingInfo;
+26 -1
View File
@@ -25,6 +25,7 @@ import {
TimingCollector,
type TimingInfo,
} from "../timing.ts";
import { TimingDump } from "../timingDump.ts";
export type { ClientOptions, ClientSocketOptions, ClientSpawnOptions };
@@ -32,6 +33,8 @@ export class Client {
private channel: SyncRpcChannel;
private encoder = new TextEncoder();
private timing: TimingCollector | undefined;
private timingDump: TimingDump | undefined;
private closed = false;
private maxResponseBytesPerPage: number | undefined;
constructor(options: ClientOptions) {
@@ -39,6 +42,10 @@ export class Client {
throw new Error("Socket connections are not yet supported in the sync client");
}
this.timingDump = TimingDump.fromEnvironment("sync", "spawn");
if (this.timingDump) {
options = { ...options, collectTiming: true };
}
const args = getAPIProcessArgs(options, false);
this.maxResponseBytesPerPage = options.maxResponseBytesPerPage;
@@ -184,6 +191,24 @@ export class Client {
}
close(): void {
this.channel.close();
if (this.closed) return;
this.closed = true;
try {
if (this.timingDump && this.timing) {
const local = this.timing.getInfo();
let server: ServerTimingInfo | undefined;
let serverTimingError: string | undefined;
try {
server = JSON.parse(this.channel.requestSync("getServerTiming", "")) as ServerTimingInfo;
}
catch (error) {
serverTimingError = String(error);
}
this.timingDump.write(local, server, serverTimingError);
}
}
finally {
this.channel.close();
}
}
}
+12 -1
View File
@@ -113,6 +113,7 @@ export class SyncRpcChannel {
private writeFd: number;
private pipeFd: number | undefined;
private callbacks = new Map<string, (name: string, payload: string) => string>();
private callbackFailure: { error: unknown; } | undefined;
private methodBufCache = new Map<string, Buffer>();
@@ -280,6 +281,9 @@ export class SyncRpcChannel {
if (this.readFd < 0) {
throw new Error("SyncRpcChannel is closed");
}
if (this.callbackFailure) {
throw this.callbackFailure.error;
}
}
private getMethodBuf(method: string): Buffer {
@@ -326,7 +330,14 @@ export class SyncRpcChannel {
);
}
case MSG_CALL: {
this.handleCall(this._msgName.toString("utf-8"), this._msgPayload);
try {
this.handleCall(this._msgName.toString("utf-8"), this._msgPayload);
}
catch (error) {
// The pending response is unread, so further I/O cannot be synchronized.
this.callbackFailure = { error };
throw error;
}
break;
}
default:
+1 -1
View File
@@ -182,7 +182,7 @@ export function disabledServerTimingInfo(): ServerTimingInfo {
* requests used to fetch timing) do not misalign the two ring buffers.
*/
export function combineTimingInfo(client: TimingInfo, server: ServerTimingInfo): TimingInfo {
if (!client.enabled) {
if (!client.enabled || !server.enabled) {
return client;
}
+55
View File
@@ -0,0 +1,55 @@
import { randomUUID } from "node:crypto";
import {
mkdirSync,
writeFileSync,
} from "node:fs";
import {
join,
resolve,
} from "node:path";
import {
combineTimingInfo,
type ServerTimingInfo,
type TimingInfo,
} from "./timing.ts";
/** One final snapshot per client, written before its connection is closed. */
export class TimingDump {
private readonly instanceId = randomUUID();
private readonly startedAt = new Date().toISOString();
private readonly directory: string;
private readonly mode: "sync" | "async";
private readonly transport: "spawn" | "socket";
static fromEnvironment(mode: "sync" | "async", transport: "spawn" | "socket"): TimingDump | undefined {
const directory = process.env.TS_API_TIMING_DIR;
return directory ? new TimingDump(resolve(directory), mode, transport) : undefined;
}
private constructor(directory: string, mode: "sync" | "async", transport: "spawn" | "socket") {
this.directory = directory;
this.mode = mode;
this.transport = transport;
}
write(client: TimingInfo, server: ServerTimingInfo | undefined, serverTimingError?: string): void {
const snapshot = {
schemaVersion: 1,
instanceId: this.instanceId,
pid: process.pid,
mode: this.mode,
transport: this.transport,
startedAt: this.startedAt,
closedAt: new Date().toISOString(),
timing: server ? combineTimingInfo(client, server) : client,
serverTiming: server ?? null,
serverTimingError,
};
mkdirSync(this.directory, { recursive: true });
writeFileSync(
join(this.directory, `timing-${process.pid}-${this.instanceId}.json`),
JSON.stringify(snapshot) + "\n",
{ flag: "wx" },
);
}
}
+132
View File
@@ -0,0 +1,132 @@
import {
createMessageConnection,
SocketMessageReader,
SocketMessageWriter,
} from "#vscode-jsonrpc/node";
import { API as AsyncAPI } from "@typescript/typescript/async";
import { API as SyncAPI } from "@typescript/typescript/sync";
import assert from "node:assert/strict";
import { once } from "node:events";
import {
mkdtempSync,
readdirSync,
readFileSync,
rmSync,
} from "node:fs";
import { createServer } from "node:net";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "node:test";
import {
combineTimingInfo,
disabledServerTimingInfo,
TimingCollector,
} from "../src/api/timing.ts";
import { createVirtualFileSystem } from "./testUtils.ts";
test("disabled server timing preserves the client-only snapshot", () => {
const collector = new TimingCollector();
collector.record({ method: "initialize", roundTripMs: 10, bytesSent: 1, bytesReceived: 1 });
const local = collector.getInfo();
assert.strictEqual(combineTimingInfo(local, disabledServerTimingInfo()), local);
});
test("timing dumps", async t => {
const directory = mkdtempSync(join(tmpdir(), "ts-timing-"));
const original = process.env.TS_API_TIMING_DIR;
t.after(() => {
if (original === undefined) delete process.env.TS_API_TIMING_DIR;
else process.env.TS_API_TIMING_DIR = original;
rmSync(directory, { recursive: true, force: true });
});
function assertDumpCount(count: number): void {
const files = readdirSync(directory).filter(file => file.endsWith(".json"));
assert.equal(files.length, count);
for (const file of files) {
assert.ok(Object.keys(JSON.parse(readFileSync(join(directory, file), "utf8"))).length > 0);
}
}
let count = 0;
for (const [mode, API] of [["async", AsyncAPI], ["sync", SyncAPI]] as const) {
for (const value of [undefined, "", directory]) {
await t.test(`${mode}: dumping ${value ? "enabled" : value === "" ? "empty" : "unset"}`, async () => {
if (value === undefined) delete process.env.TS_API_TIMING_DIR;
else process.env.TS_API_TIMING_DIR = value;
const api = new API({ collectTiming: false });
try {
await api.parseCommandLine([]);
assert.equal((await api.getTimingInfo()).enabled, !!value);
assertDumpCount(count);
}
finally {
await api.close();
}
if (value) count++;
assertDumpCount(count);
await api.close();
assertDumpCount(count);
});
}
}
process.env.TS_API_TIMING_DIR = directory;
await t.test("sync: preserves a dump after a filesystem callback throws", async t => {
const warning = t.mock.method(process, "emitWarning", () => {});
const api = new SyncAPI({
fs: {
...createVirtualFileSystem({}),
readFile() {
throw new Error("read failed");
},
},
});
try {
api.parseCommandLine([]);
assert.throws(() => api.readConfigFile("/tsconfig.json"), /read failed/);
assert.throws(() => api.parseCommandLine([]), /read failed/);
assert.throws(() => api.getTimingInfo(), /read failed/);
}
finally {
api.close();
}
assertDumpCount(++count);
assert.equal(warning.mock.callCount(), 0);
});
for (const scenario of ["error", "disconnect", "disabled"] as const) {
await t.test(`async: preserves a dump when server timing is ${scenario}`, { timeout: 5000 }, async t => {
const warning = t.mock.method(process, "emitWarning", () => {});
const pipe = process.platform === "win32" ? `\\\\.\\pipe\\ts-timing-${process.pid}` : join(directory, "api.sock");
let disconnect = () => {};
const server = createServer(socket => {
const connection = createMessageConnection(new SocketMessageReader(socket), new SocketMessageWriter(socket));
disconnect = () => {
connection.dispose();
socket.destroy();
};
connection.onRequest("initialize", () => ({ currentDirectory: process.cwd(), caseSensitivity: 1 }));
connection.onRequest("getServerTiming", () => {
if (scenario === "disconnect") {
disconnect();
return new Promise(() => {});
}
if (scenario === "disabled") return disabledServerTimingInfo();
throw new Error("server timing unavailable");
});
connection.listen();
});
t.after(() => {
disconnect();
return new Promise<void>(resolve => server.close(() => resolve()));
});
server.listen(pipe);
await once(server, "listening");
const api = await AsyncAPI.fromLSPConnection({ pipe });
await api.close();
assertDumpCount(++count);
assert.equal(warning.mock.callCount(), 0);
});
}
});
+1 -1
View File
@@ -37,7 +37,7 @@ extends:
fetchDepth: 1
fetchTags: false
retryCount: 3
sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES
sourceAnalysisPool: VSEng-MicroBuildVSStable
featureFlags:
golang:
internalModuleProxy:
+1 -1
View File
@@ -43,7 +43,7 @@ extends:
parameters:
sdl:
sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES
sourceAnalysisPool: VSEng-MicroBuildVSStable
pool:
name: AzurePipelines-EO
image: 1ESPT-Ubuntu22.04
+1 -1
View File
@@ -31,7 +31,7 @@ extends:
fetchDepth: 0
fetchTags: false
retryCount: 3
sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES
sourceAnalysisPool: VSEng-MicroBuildVSStable
pool:
name: AzurePipelines-EO
image: 1ESPT-Ubuntu22.04
@@ -38,7 +38,7 @@ extends:
parameters:
sdl:
sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES
sourceAnalysisPool: VSEng-MicroBuildVSStable
pool:
name: AzurePipelines-EO
image: 1ESPT-Ubuntu22.04
@@ -316,3 +316,49 @@ func TestCreateProgramReportsNonCompositeProjectReference(t *testing.T) {
}
assert.DeepEqual(t, codes, []int32{6306})
}
func TestCreateSnapshotResolvesPathsRelativeToParsedConfigDirectory(t *testing.T) {
t.Parallel()
const (
mainFile = "/project/main.ts"
libFile = "/project/types/lib.d.ts"
)
init, _ := projecttestutil.GetSessionInitOptions(map[string]any{
mainFile: `import { x } from "lib"; export const y: number = x;`,
libFile: `export declare const x: number;`,
}, nil, &projecttestutil.TypingsInstallerOptions{})
init.Options.CurrentDirectory = "/somewhere-else"
session := NewStandaloneSession(init, nil)
defer session.Close()
var parseParams ParseJsonConfigFileContentParams
assert.NilError(t, json.Unmarshal([]byte(`{
"json": {
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler",
"noLib": true,
"types": [],
"paths": { "lib": ["./types/lib.d.ts"] }
}
},
"configDirectory": "/project"
}`), &parseParams))
parsed, err := session.handleParseJsonConfigFileContent(context.Background(), &parseParams)
assert.NilError(t, err)
// Round-trip the parsed options through JSON as an API client would.
encodedOptions, err := json.Marshal(parsed.Options)
assert.NilError(t, err)
var createParams CreateSnapshotParams
assert.NilError(t, json.Unmarshal([]byte(`{"createPrograms":[{"rootFiles":["`+mainFile+`"],"compilerOptions":`+string(encodedOptions)+`}]}`), &createParams))
response, err := session.handleCreateSnapshot(context.Background(), &createParams)
assert.NilError(t, err)
snapshot, err := session.getSnapshotData(response.Snapshot)
assert.NilError(t, err)
program, err := snapshot.getProgram(response.Projects[0].Id)
assert.NilError(t, err)
assert.Assert(t, program.GetSourceFile(libFile) != nil, "expected 'lib' to resolve via paths relative to /project")
}
+4 -4
View File
@@ -639,7 +639,7 @@ type Checker struct {
subtypeReductionCache map[CacheHashKey][]*Type
cachedTypes map[CachedTypeKey]*Type
cachedSignatures map[CachedSignatureKey]*Signature
undefinedProperties map[string]*ast.Symbol
undefinedProperties map[*ast.Symbol]*ast.Symbol
narrowedTypes map[NarrowedTypeKey]*Type
assignmentReducedTypes map[AssignmentReducedKey]*Type
discriminatedContextualTypes map[DiscriminatedContextualTypeKey]*Type
@@ -977,7 +977,7 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) {
c.subtypeReductionCache = make(map[CacheHashKey][]*Type)
c.cachedTypes = make(map[CachedTypeKey]*Type)
c.cachedSignatures = make(map[CachedSignatureKey]*Signature)
c.undefinedProperties = make(map[string]*ast.Symbol)
c.undefinedProperties = make(map[*ast.Symbol]*ast.Symbol)
c.narrowedTypes = make(map[NarrowedTypeKey]*Type)
c.assignmentReducedTypes = make(map[AssignmentReducedKey]*Type)
c.discriminatedContextualTypes = make(map[DiscriminatedContextualTypeKey]*Type)
@@ -18927,12 +18927,12 @@ func (c *Checker) getSiblingsOfContext(context *WideningContext) []*Type {
}
func (c *Checker) getUndefinedProperty(prop *ast.Symbol) *ast.Symbol {
if cached := c.undefinedProperties[prop.Name()]; cached != nil {
if cached := c.undefinedProperties[prop]; cached != nil {
return cached
}
result := c.createSymbolWithType(prop, c.undefinedOrMissingType)
result.SetFlags(result.Flags() | ast.SymbolFlagsOptional)
c.undefinedProperties[prop.Name()] = result
c.undefinedProperties[prop] = result
return result
}
@@ -1,9 +1,19 @@
package incremental
import (
"fmt"
"maps"
"slices"
"strconv"
"testing"
"github.com/microsoft/TypeScript/tsc/internal/collections"
"github.com/microsoft/TypeScript/tsc/internal/compiler"
"github.com/microsoft/TypeScript/tsc/internal/core"
"github.com/microsoft/TypeScript/tsc/internal/json"
"github.com/microsoft/TypeScript/tsc/internal/tsoptions"
"github.com/microsoft/TypeScript/tsc/internal/tspath"
"github.com/microsoft/TypeScript/tsc/internal/vfs/vfstest"
"gotest.tools/v3/assert"
)
@@ -34,3 +44,405 @@ func TestBuildInfoPathJSONRoundTrip(t *testing.T) {
assert.DeepEqual(t, roundTripped.FileNames, buildInfo.FileNames)
assert.Equal(t, roundTripped.LatestChangedDtsFile, buildInfo.LatestChangedDtsFile)
}
const deletionTestLib = `interface Array<T> {}
interface Boolean {}
interface CallableFunction {}
interface Function {}
interface IArguments {}
interface NewableFunction {}
interface Number {}
interface Object {}
interface RegExp {}
interface String {}
`
func newDeletionTestProgram(files map[string]string, roots []string, options *core.CompilerOptions, old *Program) *Program {
files = maps.Clone(files)
files["/lib/"+tsoptions.GetDefaultLibFileName(options)] = files["/lib/lib.d.ts"]
host := compiler.NewCompilerHost(vfstest.FromMap(files, tspath.CaseSensitive), "/lib", nil, nil, nil)
paths := core.Map(roots, func(name string) tspath.RootedFilePath {
return tspath.ToRootedFilePath(name, "/project")
})
config := tsoptions.NewParsedCommandLine(options, paths, nil, "/project", tspath.CaseSensitive)
program := compiler.NewProgram(compiler.ProgramOptions{Config: config, Host: host})
return NewProgram(program, old, CreateHost(host), nil, false)
}
func TestDeletedGlobalInvalidatesAllSourceFiles(t *testing.T) {
t.Parallel()
current := newDeletionTestProgram(map[string]string{
"/lib/lib.d.ts": deletionTestLib,
"/project/consumer.ts": "export const unchanged = 1;",
}, []string{"consumer.ts"}, &core.CompilerOptions{Incremental: core.TSTrue, NoEmit: core.TSTrue}, nil)
old := &Program{snapshot: &snapshot{}}
current.snapshot.fileInfos.Range(func(path tspath.PathKey, info *FileInfo) bool {
old.snapshot.fileInfos.Store(path, info)
return true
})
for _, path := range []tspath.PathKey{"/project/first.d.ts", "/project/second.d.ts"} {
old.snapshot.fileInfos.Store(path, &FileInfo{})
}
deletedOrder := func() []tspath.PathKey {
var paths []tspath.PathKey
old.snapshot.fileInfos.Range(func(path tspath.PathKey, _ *FileInfo) bool {
if _, retained := current.snapshot.fileInfos.Load(path); !retained {
paths = append(paths, path)
}
return true
})
return paths
}
order := deletedOrder()
if !slices.Equal(order, deletedOrder()) {
t.Fatal("file iteration changed without writes")
}
info, _ := old.snapshot.fileInfos.Load(order[len(order)-1])
info.affectsGlobalScope = true
to := &toProgramSnapshot{program: current.program, snapshot: current.snapshot, oldProgram: old}
to.handleFileDelete()
if !to.globalFileRemoved || !current.snapshot.changedFilesSet.Has("/project/consumer.ts") {
t.Fatalf("global deletion after non-global deletion did not invalidate consumer: global=%t changed=%t",
to.globalFileRemoved, current.snapshot.changedFilesSet.Has("/project/consumer.ts"))
}
}
func TestGlobalDeletionInvalidatesRetainedLibraryDiagnostics(t *testing.T) {
t.Parallel()
for _, single := range []core.Tristate{core.TSFalse, core.TSTrue} {
for _, kind := range []string{"new error", "cleared error", "scope loss"} {
t.Run(fmt.Sprintf("%v/%s", single, kind), func(t *testing.T) {
t.Parallel()
options := &core.CompilerOptions{
Incremental: core.TSTrue, NoEmit: core.TSTrue,
SingleThreaded: single, TsBuildInfoFile: "/project/state.tsbuildinfo",
}
library := deletionTestLib + "interface LibraryConsumer { property: RemovedGlobal; }"
global := "interface RemovedGlobal { x: string; }"
if kind == "cleared error" {
library = deletionTestLib + "interface Shared<T> {}"
global = "interface Shared<T, U> {}"
}
files := map[string]string{
"/lib/lib.d.ts": library,
"/project/global.d.ts": global,
"/project/consumer.ts": "export const unchanged = 1;",
"/project/module.d.ts": "export interface Unrelated {}",
}
old := newDeletionTestProgram(files, []string{"global.d.ts", "consumer.ts", "module.d.ts"}, options, nil)
old.GetSemanticDiagnostics(t.Context(), nil)
old.Emit(t.Context(), compiler.EmitOptions{})
roots := []string{"consumer.ts"}
if kind == "scope loss" {
files["/project/global.d.ts"] = "export " + global
roots = append(roots, "global.d.ts")
} else {
delete(files, "/project/global.d.ts")
}
delete(files, "/project/module.d.ts")
current := newDeletionTestProgram(files, roots, options, old)
cold := newDeletionTestProgram(files, roots, options, nil)
actual := current.GetSemanticDiagnostics(t.Context(), nil)
expected := cold.GetSemanticDiagnostics(t.Context(), nil)
if kind == "cleared error" {
if len(expected) != 0 {
t.Fatalf("cold build should have no errors: %v", expected)
}
} else if len(expected) != 1 || expected[0].Code() != 2304 {
t.Fatalf("cold build should report one TS2304: %v", expected)
}
if len(actual) != len(expected) {
t.Fatalf("incremental diagnostics=%d, cold=%d", len(actual), len(expected))
}
if len(actual) != 0 && actual[0].Code() != expected[0].Code() {
t.Fatalf("incremental diagnostic=%d, cold=%d", actual[0].Code(), expected[0].Code())
}
})
}
}
}
func TestEmptyProgramDeletionEmitsBuildInfo(t *testing.T) {
t.Parallel()
for flags := range 8 {
for _, roots := range [][]string{{"global.d.ts"}, {"module.d.ts"}, {"global.d.ts", "module.d.ts"}} {
t.Run(fmt.Sprintf("%d/%v", flags, roots), func(t *testing.T) {
t.Parallel()
options := &core.CompilerOptions{
Incremental: core.TSTrue, TsBuildInfoFile: "/project/state.tsbuildinfo",
NoCheck: core.IfElse(flags&1 != 0, core.TSTrue, core.TSFalse),
NoEmit: core.IfElse(flags&2 != 0, core.TSTrue, core.TSFalse),
Composite: core.IfElse(flags&4 != 0, core.TSTrue, core.TSFalse),
}
files := map[string]string{
"/lib/lib.d.ts": deletionTestLib,
"/project/global.d.ts": "interface RemovedGlobal {}",
"/project/module.d.ts": "export interface Unrelated {}",
}
old := newDeletionTestProgram(files, roots, options, nil)
old.GetSemanticDiagnostics(t.Context(), nil)
old.Emit(t.Context(), compiler.EmitOptions{})
if old.snapshot.buildInfoEmitPending.Load() {
t.Fatal("initial build info was not emitted")
}
delete(files, "/project/global.d.ts")
delete(files, "/project/module.d.ts")
current := newDeletionTestProgram(files, nil, options, old)
if len(current.GetSourceFiles()) != 0 {
t.Fatal("new program is not empty")
}
writes := 0
current.Emit(t.Context(), compiler.EmitOptions{
WriteFile: func(name tspath.RootedFilePath, text string, _ *compiler.WriteFileData) error {
if name.ExtensionIs(tspath.ExtensionTsBuildInfo) {
writes++
var info struct {
FileNames []string `json:"fileNames"`
FileInfos []json.Value `json:"fileInfos"`
ChangeFileSet []int `json:"changeFileSet"`
AffectedFilesPendingEmit []json.Value `json:"affectedFilesPendingEmit"`
}
if err := json.Unmarshal([]byte(text), &info); err != nil {
t.Fatal(err)
}
if len(info.FileNames) != 0 || len(info.FileInfos) != 0 || len(info.ChangeFileSet) != 0 || len(info.AffectedFilesPendingEmit) != 0 {
t.Fatalf("empty program persisted removed state: %+v", info)
}
}
return nil
},
})
if writes != 1 {
t.Fatalf("build-info writes after deleting every source = %d, want 1", writes)
}
})
}
}
}
func TestUncheckedDeletedFilesDiscardPendingState(t *testing.T) {
t.Parallel()
options := &core.CompilerOptions{
Incremental: core.TSTrue, NoEmit: core.TSTrue, NoCheck: core.TSTrue,
TsBuildInfoFile: "/project/state.tsbuildinfo",
}
files := map[string]string{
"/lib/lib.d.ts": deletionTestLib,
"/project/stable.ts": "export const stable = 1;",
}
old := newDeletionTestProgram(files, []string{"stable.ts"}, options, nil)
old.Emit(t.Context(), compiler.EmitOptions{})
files["/project/first.ts"] = "export const first = 1;"
files["/project/second.ts"] = "export const second = 1;"
added := newDeletionTestProgram(files, []string{"stable.ts", "first.ts", "second.ts"}, options, old)
added.Emit(t.Context(), compiler.EmitOptions{})
for _, path := range []tspath.PathKey{"/project/first.ts", "/project/second.ts"} {
if !added.snapshot.changedFilesSet.Has(path) {
t.Fatalf("new unchecked file %s not pending", path)
}
added.snapshot.affectedFilesPendingEmit.Store(path, FileEmitKindJs)
}
delete(files, "/project/first.ts")
delete(files, "/project/second.ts")
current := newDeletionTestProgram(files, []string{"stable.ts"}, options, added)
for _, path := range []tspath.PathKey{"/project/first.ts", "/project/second.ts"} {
if current.snapshot.changedFilesSet.Has(path) {
t.Errorf("removed unchecked file %s still in change set", path)
}
if _, pending := current.snapshot.affectedFilesPendingEmit.Load(path); pending {
t.Errorf("removed file %s still pending emit", path)
}
}
info, err := snapshotToBuildInfo(current.snapshot, current.program, options.TsBuildInfoFile)
if err != nil {
t.Fatal(err)
}
if len(info.FileNames) != len(info.FileInfos) || len(info.ChangeFileSet) != 0 {
t.Fatalf("invalid build-info file state: names=%d infos=%d changes=%v", len(info.FileNames), len(info.FileInfos), info.ChangeFileSet)
}
}
func TestModuleDeletionPreservesUnrelatedCachedDiagnostics(t *testing.T) {
t.Parallel()
for _, skip := range []core.Tristate{core.TSFalse, core.TSTrue} {
t.Run(fmt.Sprint(skip), func(t *testing.T) {
t.Parallel()
options := &core.CompilerOptions{
Incremental: core.TSTrue, NoEmit: core.TSTrue, SkipDefaultLibCheck: skip,
TsBuildInfoFile: "/project/state.tsbuildinfo",
}
files := map[string]string{
"/lib/lib.d.ts": deletionTestLib,
"/project/consumer.ts": "export const unchanged = 1;",
"/project/module.d.ts": "export interface Unrelated {}",
}
old := newDeletionTestProgram(files, []string{"consumer.ts", "module.d.ts"}, options, nil)
old.GetSemanticDiagnostics(t.Context(), nil)
old.Emit(t.Context(), compiler.EmitOptions{})
delete(files, "/project/module.d.ts")
current := newDeletionTestProgram(files, []string{"consumer.ts"}, options, old)
if current.snapshot.changedFilesSet.Has("/project/consumer.ts") {
t.Fatal("unrelated module deletion invalidated consumer")
}
for _, file := range current.GetSourceFiles() {
previous, ok := old.snapshot.semanticDiagnosticsPerFile.Load(file.PathKey())
if !ok {
t.Fatalf("initial diagnostics for %s were not cached", file.FileName())
}
cached, ok := current.snapshot.semanticDiagnosticsPerFile.Load(file.PathKey())
if !ok || cached != previous {
t.Fatalf("unrelated cached diagnostics for %s not reused", file.FileName())
}
}
})
}
}
func TestDeletedFilesCleanupAfterGlobalDeletion(t *testing.T) {
t.Parallel()
current := newDeletionTestProgram(map[string]string{"/lib/lib.d.ts": deletionTestLib}, nil,
&core.CompilerOptions{Incremental: core.TSTrue}, nil)
old := &Program{snapshot: &snapshot{}}
deleted := []tspath.PathKey{"/project/first.d.ts", "/project/second.d.ts", "/project/third.d.ts"}
for _, path := range deleted {
old.snapshot.fileInfos.Store(path, &FileInfo{affectsGlobalScope: true})
current.snapshot.changedFilesSet.Add(path)
current.snapshot.affectedFilesPendingEmit.Store(path, FileEmitKindJs)
}
to := &toProgramSnapshot{program: current.program, snapshot: current.snapshot, oldProgram: old}
to.handleFileDelete()
for _, path := range deleted {
if current.snapshot.changedFilesSet.Has(path) {
t.Errorf("removed path %s still in change set", path)
}
if _, pending := current.snapshot.affectedFilesPendingEmit.Load(path); pending {
t.Errorf("removed path %s still pending emit", path)
}
}
if !current.snapshot.buildInfoEmitPending.Load() {
t.Error("global deletion did not mark build info pending")
}
}
func TestRemovedPendingPathsWithoutFileInfo(t *testing.T) {
t.Parallel()
options := &core.CompilerOptions{
Incremental: core.TSTrue, NoCheck: core.TSTrue, NoEmit: core.TSTrue,
TsBuildInfoFile: "/project/state.tsbuildinfo",
}
files := map[string]string{
"/lib/lib.d.ts": deletionTestLib,
"/project/stable.ts": "export const stable = 1;",
}
old := newDeletionTestProgram(files, []string{"stable.ts"}, options, nil)
old.Emit(t.Context(), compiler.EmitOptions{})
old.snapshot.changedFilesSet.Add("/project/missing.ts")
old.snapshot.affectedFilesPendingEmit.Store("/project/missing.ts", FileEmitKindJs)
current := newDeletionTestProgram(files, []string{"stable.ts"}, options, old)
if current.snapshot.changedFilesSet.Has("/project/missing.ts") {
t.Error("removed pending path without file info was retained")
}
if _, pending := current.snapshot.affectedFilesPendingEmit.Load("/project/missing.ts"); pending {
t.Error("removed pending emit path without file info was retained")
}
if !current.snapshot.buildInfoEmitPending.Load() {
t.Error("discarding obsolete pending state did not mark build info pending")
}
info, err := snapshotToBuildInfo(current.snapshot, current.program, options.TsBuildInfoFile)
if err != nil {
t.Fatal(err)
}
if len(info.FileNames) != len(info.FileInfos) {
t.Fatalf("invalid cached file state: names=%d infos=%d", len(info.FileNames), len(info.FileInfos))
}
}
func TestForEachDeletedFileVisitsEveryRemovedPath(t *testing.T) {
t.Parallel()
order := []tspath.PathKey{"/first.ts", "/second.ts", "/third.ts", "/fourth.ts"}
var visitOrders func(int)
visitOrders = func(index int) {
if index != len(order) {
for next := index; next < len(order); next++ {
order[index], order[next] = order[next], order[index]
visitOrders(index + 1)
order[index], order[next] = order[next], order[index]
}
return
}
for retained := range 16 {
for global := range 16 {
var current collections.SyncMap[tspath.PathKey, *FileInfo]
infos := make(map[tspath.PathKey]*FileInfo)
var expected []tspath.PathKey
for i, path := range order {
infos[path] = &FileInfo{affectsGlobalScope: global&(1<<i) != 0}
if retained&(1<<i) != 0 {
current.Store(path, &FileInfo{})
} else {
expected = append(expected, path)
}
}
current.Store("/new.ts", &FileInfo{})
var actual []tspath.PathKey
forEachDeletedFile(func(callback func(tspath.PathKey, *FileInfo) bool) {
for _, path := range order {
if !callback(path, infos[path]) {
t.Fatal("deleted-file enumeration stopped early")
}
}
}, &current, func(path tspath.PathKey, info *FileInfo) {
if info != infos[path] {
t.Fatal("deleted-file callback lost old metadata")
}
actual = append(actual, path)
})
if !slices.Equal(actual, expected) {
t.Fatalf("order=%v retained=%d global=%d: callbacks=%v, want %v", order, retained, global, actual, expected)
}
}
}
}
visitOrders(0)
}
func TestGlobalDeletionPreservesSkippedLibraryDiagnostics(t *testing.T) {
t.Parallel()
for _, skipDefault := range []bool{false, true} {
t.Run(strconv.FormatBool(skipDefault), func(t *testing.T) {
t.Parallel()
options := &core.CompilerOptions{Incremental: core.TSTrue, NoEmit: core.TSTrue}
if skipDefault {
options.SkipDefaultLibCheck = core.TSTrue
} else {
options.SkipLibCheck = core.TSTrue
}
files := map[string]string{
"/lib/lib.d.ts": deletionTestLib + "interface LibraryConsumer { property: RemovedGlobal; }",
"/project/global.d.ts": "interface RemovedGlobal {}",
"/project/consumer.ts": "export const unchanged = 1;",
}
old := newDeletionTestProgram(files, []string{"consumer.ts", "global.d.ts"}, options, nil)
old.GetSemanticDiagnostics(t.Context(), nil)
old.Emit(t.Context(), compiler.EmitOptions{})
delete(files, "/project/global.d.ts")
current := newDeletionTestProgram(files, []string{"consumer.ts"}, options, old)
for _, file := range current.GetSourceFiles() {
if !current.program.IsSourceFileDefaultLibrary(file.PathKey()) {
continue
}
previous, ok := old.snapshot.semanticDiagnosticsPerFile.Load(file.PathKey())
cached, reused := current.snapshot.semanticDiagnosticsPerFile.Load(file.PathKey())
if !ok || !reused || cached != previous {
t.Fatalf("skipped library diagnostics for %s not reused", file.FileName())
}
if current.snapshot.changedFilesSet.Has(file.PathKey()) {
t.Fatalf("global removal marked skipped library %s changed", file.FileName())
}
}
if diagnostics := current.GetSemanticDiagnostics(t.Context(), nil); len(diagnostics) != 0 {
t.Fatalf("skipped library produced diagnostics: %v", diagnostics)
}
})
}
}
@@ -51,16 +51,24 @@ func (t *toProgramSnapshot) reuseFromOldProgram() {
if t.snapshot.options.Composite.IsTrue() {
t.snapshot.latestChangedDtsFile = t.oldProgram.snapshot.latestChangedDtsFile
}
t.snapshot.buildInfoEmitPending.Store(t.oldProgram.snapshot.buildInfoEmitPending.Load())
// Copy old snapshot's changed files set
t.oldProgram.snapshot.changedFilesSet.Range(func(key tspath.PathKey) bool {
t.snapshot.changedFilesSet.Add(key)
if t.program.GetSourceFileByPath(key) != nil {
t.snapshot.changedFilesSet.Add(key)
} else {
t.snapshot.buildInfoEmitPending.Store(true)
}
return true
})
t.oldProgram.snapshot.affectedFilesPendingEmit.Range(func(key tspath.PathKey, emitKind FileEmitKind) bool {
t.snapshot.affectedFilesPendingEmit.Store(key, emitKind)
if t.program.GetSourceFileByPath(key) != nil {
t.snapshot.affectedFilesPendingEmit.Store(key, emitKind)
} else {
t.snapshot.buildInfoEmitPending.Store(true)
}
return true
})
t.snapshot.buildInfoEmitPending.Store(t.oldProgram.snapshot.buildInfoEmitPending.Load())
t.snapshot.hasErrorsFromOldState = t.oldProgram.snapshot.hasErrors
t.snapshot.hasSemanticErrorsFromOldState = t.oldProgram.snapshot.hasSemanticErrors
t.snapshot.packageJsonsFromOldState = t.oldProgram.snapshot.packageJsons
@@ -161,21 +169,41 @@ func (t *toProgramSnapshot) computeProgramFileChanges() {
func (t *toProgramSnapshot) handleFileDelete() {
if t.oldProgram != nil {
// If the global file is removed, add all files as changed
t.oldProgram.snapshot.fileInfos.Range(func(filePath tspath.PathKey, oldInfo *FileInfo) bool {
if _, ok := t.snapshot.fileInfos.Load(filePath); !ok {
if oldInfo.affectsGlobalScope {
for _, file := range t.snapshot.getAllFilesExcludingDefaultLibraryFile(t.program, nil) {
t.snapshot.addFileToChangeSet(file.PathKey())
}
t.globalFileRemoved = true
} else {
t.snapshot.buildInfoEmitPending.Store(true)
}
return false
}
return true
})
forEachDeletedFile(t.oldProgram.snapshot.fileInfos.Range, &t.snapshot.fileInfos, t.handleDeletedFile)
if t.globalFileRemoved {
t.invalidateGlobalScope()
}
}
}
func forEachDeletedFile(
rangeOldFileInfos func(func(tspath.PathKey, *FileInfo) bool),
newFileInfos *collections.SyncMap[tspath.PathKey, *FileInfo],
onDeletedFile func(tspath.PathKey, *FileInfo),
) {
rangeOldFileInfos(func(filePath tspath.PathKey, oldInfo *FileInfo) bool {
if _, retained := newFileInfos.Load(filePath); !retained {
onDeletedFile(filePath, oldInfo)
}
return true
})
}
func (t *toProgramSnapshot) handleDeletedFile(filePath tspath.PathKey, oldInfo *FileInfo) {
t.snapshot.buildInfoEmitPending.Store(true)
t.snapshot.changedFilesSet.Delete(filePath)
t.snapshot.affectedFilesPendingEmit.Delete(filePath)
t.globalFileRemoved = t.globalFileRemoved || oldInfo.affectsGlobalScope
}
func (t *toProgramSnapshot) invalidateGlobalScope() {
t.snapshot.buildInfoEmitPending.Store(true)
for _, file := range t.program.GetSourceFiles() {
if !t.program.IsSourceFileDefaultLibrary(file.PathKey()) {
t.snapshot.addFileToChangeSet(file.PathKey())
} else if !t.program.SkipTypeChecking(file, true) {
t.snapshot.semanticDiagnosticsPerFile.Delete(file.PathKey())
}
}
}
@@ -195,9 +223,7 @@ func (t *toProgramSnapshot) handleGlobalScopeChange() {
return true
})
if globalScopeLost {
for _, file := range t.snapshot.getAllFilesExcludingDefaultLibraryFile(t.program, nil) {
t.snapshot.addFileToChangeSet(file.PathKey())
}
t.invalidateGlobalScope()
}
}
+184
View File
@@ -325,6 +325,43 @@ func TestTscCommandline(t *testing.T) {
},
}
for _, value := range []string{"false", "true", "omitted"} {
option := ""
if value != "omitted" {
option = `, "alwaysStrict": ` + value
}
testCases = append(testCases, &tscInput{
subScenario: "alwaysStrict " + value + " in configuration",
files: FileMap{
"/home/src/workspaces/project/tsconfig.json": fmt.Sprintf(`{"compilerOptions": {"target": "es2015"%s}}`, option),
"/home/src/workspaces/project/index.ts": "export {};",
},
commandLineArgs: []string{"--noEmit"},
})
}
for _, setting := range []struct {
name string
config string
base string
}{
{"relative", `{"compilerOptions": {"target": "es2015", "baseUrl": "."}}`, ""},
{"empty", `{"compilerOptions": {"target": "es2015", "baseUrl": ""}}`, ""},
{"inherited", `{"extends": "./base.json"}`, `{"compilerOptions": {"target": "es2015", "baseUrl": "."}}`},
{"omitted", `{"compilerOptions": {"target": "es2015"}}`, ""},
} {
files := FileMap{
"/home/src/workspaces/project/tsconfig.json": setting.config,
"/home/src/workspaces/project/index.ts": "export {};",
}
if setting.base != "" {
files["/home/src/workspaces/project/base.json"] = setting.base
}
testCases = append(testCases, &tscInput{
subScenario: "baseUrl " + setting.name + " in configuration",
files: files,
commandLineArgs: []string{"--noEmit"},
})
}
for _, testCase := range testCases {
testCase.run(t, "commandLine")
}
@@ -2569,6 +2606,153 @@ func TestTscIncremental(t *testing.T) {
}
}
func TestTscIncrementalDeletion(t *testing.T) {
t.Parallel()
for _, mode := range []struct {
name string
args []string
}{
{},
{" with single threaded", []string{"--singleThreaded"}},
{" with one checker", []string{"--checkers", "1"}},
} {
config := func(options string) string {
return `{"compilerOptions":{"incremental":true,"noEmit":true,"types":[]` + options + `},"files":["a.ts"]}`
}
(&tscInput{
subScenario: "lib and target changes delete mixed library files" + mode.name,
commandLineArgs: mode.args,
files: FileMap{
"/home/src/workspaces/project/tsconfig.json": config(`,"target":"esnext"`),
"/home/src/workspaces/project/a.ts": `export const values = [3, 1, 2].toSorted();`,
getTestLibPathFor("es5"): tscDefaultLibContent,
getTestLibPathFor("esnext.array"): stringtestutil.Dedent(`
/// <reference no-default-lib="true"/>
interface Array<T> {
toSorted(): T[];
}
`),
getTestLibPathFor("decorators"): stringtestutil.Dedent(`
/// <reference no-default-lib="true"/>
export {};
`),
getTestLibPathFor("esnext.full"): stringtestutil.Dedent(`
/// <reference no-default-lib="true"/>
/// <reference lib="es5"/>
/// <reference lib="esnext.array"/>
/// <reference lib="decorators"/>
`),
getTestLibPathFor("es2020"): stringtestutil.Dedent(`
/// <reference no-default-lib="true"/>
/// <reference lib="es5"/>
`),
getTestLibPathFor("es2020.full"): stringtestutil.Dedent(`
/// <reference no-default-lib="true"/>
/// <reference lib="es5"/>
`),
},
edits: []*tscEdit{
{caption: "narrow lib", edit: func(sys *TestSys) {
sys.writeFileNoError("/home/src/workspaces/project/tsconfig.json", config(`,"target":"esnext","lib":["es2020"]`))
}},
noChange,
{caption: "restore lib", edit: func(sys *TestSys) {
sys.writeFileNoError("/home/src/workspaces/project/tsconfig.json", config(`,"target":"esnext"`))
}},
{caption: "narrow target", edit: func(sys *TestSys) {
sys.writeFileNoError("/home/src/workspaces/project/tsconfig.json", config(`,"target":"es2020"`))
}},
noChange,
{caption: "restore target", edit: func(sys *TestSys) {
sys.writeFileNoError("/home/src/workspaces/project/tsconfig.json", config(`,"target":"esnext"`))
}},
noChange,
},
}).run(t, "incremental")
(&tscInput{
subScenario: "mixed file deletion with add and change" + mode.name,
commandLineArgs: mode.args,
files: FileMap{
"/home/src/workspaces/project/tsconfig.json": `{"compilerOptions":{"incremental":true,"noEmit":true,"types":[]}}`,
"/home/src/workspaces/project/consumer.ts": `declare const value: RemovedGlobal; value.property;`,
"/home/src/workspaces/project/global.d.ts": `interface RemovedGlobal { property: string; }`,
"/home/src/workspaces/project/module.d.ts": `export interface ModuleOnly { property: string; }`,
"/home/src/workspaces/project/changed.ts": `export const changed = 1;`,
},
edits: []*tscEdit{
{caption: "delete global and non-global files while adding and changing sources", edit: func(sys *TestSys) {
sys.removeNoError("/home/src/workspaces/project/global.d.ts")
sys.removeNoError("/home/src/workspaces/project/module.d.ts")
sys.replaceFileText("/home/src/workspaces/project/changed.ts", "1", "2")
sys.writeFileNoError("/home/src/workspaces/project/added.ts", `export const added = 1;`)
}},
noChange,
{caption: "restore global file", edit: func(sys *TestSys) {
sys.writeFileNoError("/home/src/workspaces/project/global.d.ts", `interface RemovedGlobal { property: number; }`)
}},
{caption: "delete ordinary source file", edit: func(sys *TestSys) {
sys.removeNoError("/home/src/workspaces/project/added.ts")
}},
noChange,
},
}).run(t, "incremental")
for _, cleared := range []bool{false, true} {
library := tscDefaultLibContent + "\ninterface LibraryConsumer { property: RemovedGlobal; }"
global := "interface RemovedGlobal {}"
if cleared {
library = tscDefaultLibContent + "\ninterface Shared<T> {}"
global = "interface Shared<T, U> {}"
}
(&tscInput{
subScenario: fmt.Sprintf("retained library diagnostics after global deletion cleared %t%s", cleared, mode.name),
commandLineArgs: mode.args,
files: FileMap{
"/home/src/workspaces/project/tsconfig.json": `{"compilerOptions":{"incremental":true,"noEmit":true,"types":[],"lib":["es5"]}}`,
"/home/src/workspaces/project/consumer.ts": "export const unchanged = 1;",
"/home/src/workspaces/project/global.d.ts": global,
"/home/src/workspaces/project/module.d.ts": "export interface Unrelated {}",
getTestLibPathFor("es5"): library,
},
edits: []*tscEdit{
{caption: "delete global and module declarations", edit: func(sys *TestSys) {
sys.removeNoError("/home/src/workspaces/project/global.d.ts")
sys.removeNoError("/home/src/workspaces/project/module.d.ts")
}},
noChange,
{caption: "restore global declaration", edit: func(sys *TestSys) {
sys.writeFileNoError("/home/src/workspaces/project/global.d.ts", global)
}},
noChange,
},
}).run(t, "incremental")
}
}
for _, composite := range []bool{false, true} {
(&tscInput{
subScenario: fmt.Sprintf("unchecked deleted paths with no emit composite %t", composite),
files: FileMap{
"/home/src/workspaces/project/tsconfig.json": fmt.Sprintf(`{"compilerOptions":{"incremental":true,"noCheck":true,"noEmit":true,"composite":%t,"types":[]}}`, composite),
"/home/src/workspaces/project/stable.ts": "export const stable = 1;",
},
edits: []*tscEdit{
{caption: "add unchecked sources", edit: func(sys *TestSys) {
sys.writeFileNoError("/home/src/workspaces/project/first.ts", "export const first = 1;")
sys.writeFileNoError("/home/src/workspaces/project/second.ts", "export const second = 1;")
}},
{caption: "delete unchecked sources", edit: func(sys *TestSys) {
sys.removeNoError("/home/src/workspaces/project/first.ts")
sys.removeNoError("/home/src/workspaces/project/second.ts")
}},
noChange,
{caption: "enable checking and emit", edit: func(sys *TestSys) {
sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", `"noCheck":true,"noEmit":true`, `"noCheck":false,"noEmit":false`)
}},
noChange,
},
}).run(t, "incremental")
}
}
func TestTscLibraryResolution(t *testing.T) {
t.Parallel()
getTscLibraryResolutionFileMap := func(libReplacement bool) FileMap {
@@ -85,6 +85,8 @@ func (o *RawCompilerOptions) Finalize(basePath tspath.RootedDirectoryPath) (*cor
}
} else if key == "configFilePath" {
pathKind = CommandLineOptionPathKindFile
} else if key == "pathsBasePath" {
pathKind = CommandLineOptionPathKindDirectory
} else if key != "allowNonTsExtensions" && key != "suppressOutputPathCheck" {
continue
}
@@ -27,6 +27,7 @@ func TestRawCompilerOptionsFinalizePaths(t *testing.T) {
"allowNonTsExtensions": true,
"suppressOutputPathCheck": true,
"configFilePath": "",
"pathsBasePath": "config",
"NoImplicitAny": true
}`), &raw))
@@ -46,5 +47,6 @@ func TestRawCompilerOptionsFinalizePaths(t *testing.T) {
assert.Equal(t, options.AllowNonTsExtensions, core.TSTrue)
assert.Equal(t, options.SuppressOutputPathCheck, core.TSTrue)
assert.Equal(t, options.ConfigFilePath, tspath.RootedFilePath(""))
assert.Equal(t, options.PathsBasePath, tspath.RootedDirectoryPath("/project/config"))
assert.Equal(t, options.NoImplicitAny, core.TSUnknown)
}
@@ -0,0 +1,17 @@
//// [tests/cases/compiler/assertedGenericPartialIndexedAssignment.ts] ////
=== assertedGenericPartialIndexedAssignment.ts ===
function write<T extends Record<string, unknown>>(values: Partial<T>, key: string) {
>write : Symbol(write, Decl(assertedGenericPartialIndexedAssignment.ts, 0, 0))
>T : Symbol(T, Decl(assertedGenericPartialIndexedAssignment.ts, 0, 15))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
>values : Symbol(values, Decl(assertedGenericPartialIndexedAssignment.ts, 0, 50))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(assertedGenericPartialIndexedAssignment.ts, 0, 15))
>key : Symbol(key, Decl(assertedGenericPartialIndexedAssignment.ts, 0, 69))
(values[key] as unknown) = 0;
>values : Symbol(values, Decl(assertedGenericPartialIndexedAssignment.ts, 0, 50))
>key : Symbol(key, Decl(assertedGenericPartialIndexedAssignment.ts, 0, 69))
}
@@ -0,0 +1,18 @@
//// [tests/cases/compiler/assertedGenericPartialIndexedAssignment.ts] ////
=== assertedGenericPartialIndexedAssignment.ts ===
function write<T extends Record<string, unknown>>(values: Partial<T>, key: string) {
>write : <T extends Record<string, unknown>>(values: Partial<T>, key: string) => void
>values : Partial<T>
>key : string
(values[key] as unknown) = 0;
>(values[key] as unknown) = 0 : 0
>(values[key] as unknown) : unknown
>values[key] as unknown : unknown
>values[key] : T[string] | undefined
>values : Partial<T>
>key : string
>0 : 0
}
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/assertedReadonlyParameterPropertyAssignment.ts] ////
=== assertedReadonlyParameterPropertyAssignment.ts ===
class ReadonlyState {
>ReadonlyState : Symbol(ReadonlyState, Decl(assertedReadonlyParameterPropertyAssignment.ts, 0, 0))
constructor(readonly value: object) {}
>value : Symbol(ReadonlyState.value, Decl(assertedReadonlyParameterPropertyAssignment.ts, 1, 16))
clear() {
>clear : Symbol(ReadonlyState.clear, Decl(assertedReadonlyParameterPropertyAssignment.ts, 1, 42))
(this.value as unknown) = null;
>this.value : Symbol(ReadonlyState.value, Decl(assertedReadonlyParameterPropertyAssignment.ts, 1, 16))
>this : Symbol(ReadonlyState, Decl(assertedReadonlyParameterPropertyAssignment.ts, 0, 0))
>value : Symbol(ReadonlyState.value, Decl(assertedReadonlyParameterPropertyAssignment.ts, 1, 16))
}
}
@@ -0,0 +1,22 @@
//// [tests/cases/compiler/assertedReadonlyParameterPropertyAssignment.ts] ////
=== assertedReadonlyParameterPropertyAssignment.ts ===
class ReadonlyState {
>ReadonlyState : ReadonlyState
constructor(readonly value: object) {}
>value : object
clear() {
>clear : () => void
(this.value as unknown) = null;
>(this.value as unknown) = null : null
>(this.value as unknown) : unknown
>this.value as unknown : unknown
>this.value : object
>this : this
>value : object
}
}
@@ -0,0 +1,29 @@
//// [tests/cases/compiler/callableConstructorUnionMetadata.ts] ////
=== callableConstructorUnionMetadata.ts ===
type Component<Props> = ((props: Props) => number) | (new (props: Props) => object);
>Component : Symbol(Component, Decl(callableConstructorUnionMetadata.ts, 0, 0))
>Props : Symbol(Props, Decl(callableConstructorUnionMetadata.ts, 0, 15))
>props : Symbol(props, Decl(callableConstructorUnionMetadata.ts, 0, 26))
>Props : Symbol(Props, Decl(callableConstructorUnionMetadata.ts, 0, 15))
>props : Symbol(props, Decl(callableConstructorUnionMetadata.ts, 0, 59))
>Props : Symbol(Props, Decl(callableConstructorUnionMetadata.ts, 0, 15))
type Field<Props> = Component<Props> & { testIds?: {} };
>Field : Symbol(Field, Decl(callableConstructorUnionMetadata.ts, 0, 84))
>Props : Symbol(Props, Decl(callableConstructorUnionMetadata.ts, 1, 11))
>Component : Symbol(Component, Decl(callableConstructorUnionMetadata.ts, 0, 0))
>Props : Symbol(Props, Decl(callableConstructorUnionMetadata.ts, 1, 11))
>testIds : Symbol(testIds, Decl(callableConstructorUnionMetadata.ts, 1, 40))
declare const component: <Props>(props: Props) => number;
>component : Symbol(component, Decl(callableConstructorUnionMetadata.ts, 3, 13))
>Props : Symbol(Props, Decl(callableConstructorUnionMetadata.ts, 3, 26))
>props : Symbol(props, Decl(callableConstructorUnionMetadata.ts, 3, 33))
>Props : Symbol(Props, Decl(callableConstructorUnionMetadata.ts, 3, 26))
const field: Field<string> = component;
>field : Symbol(field, Decl(callableConstructorUnionMetadata.ts, 4, 5))
>Field : Symbol(Field, Decl(callableConstructorUnionMetadata.ts, 0, 84))
>component : Symbol(component, Decl(callableConstructorUnionMetadata.ts, 3, 13))
@@ -0,0 +1,20 @@
//// [tests/cases/compiler/callableConstructorUnionMetadata.ts] ////
=== callableConstructorUnionMetadata.ts ===
type Component<Props> = ((props: Props) => number) | (new (props: Props) => object);
>Component : Component<Props>
>props : Props
>props : Props
type Field<Props> = Component<Props> & { testIds?: {} };
>Field : Field<Props>
>testIds : {} | undefined
declare const component: <Props>(props: Props) => number;
>component : <Props>(props: Props) => number
>props : Props
const field: Field<string> = component;
>field : Field<string>
>component : <Props>(props: Props) => number
@@ -0,0 +1,15 @@
//// [tests/cases/compiler/callableWeakMetadata.ts] ////
=== callableWeakMetadata.ts ===
type Initializer = (() => number) & { mutators?: [] };
>Initializer : Symbol(Initializer, Decl(callableWeakMetadata.ts, 0, 0))
>mutators : Symbol(mutators, Decl(callableWeakMetadata.ts, 0, 37))
declare function createStore(initializer: Initializer): void;
>createStore : Symbol(createStore, Decl(callableWeakMetadata.ts, 0, 54))
>initializer : Symbol(initializer, Decl(callableWeakMetadata.ts, 2, 29))
>Initializer : Symbol(Initializer, Decl(callableWeakMetadata.ts, 0, 0))
createStore(() => 1);
>createStore : Symbol(createStore, Decl(callableWeakMetadata.ts, 0, 54))
@@ -0,0 +1,17 @@
//// [tests/cases/compiler/callableWeakMetadata.ts] ////
=== callableWeakMetadata.ts ===
type Initializer = (() => number) & { mutators?: [] };
>Initializer : Initializer
>mutators : [] | undefined
declare function createStore(initializer: Initializer): void;
>createStore : (initializer: Initializer) => void
>initializer : Initializer
createStore(() => 1);
>createStore(() => 1) : void
>createStore : (initializer: Initializer) => void
>() => 1 : () => number
>1 : 1
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/callableWeakMetadataCallSuggestion.ts] ////
=== callableWeakMetadataCallSuggestion.ts ===
type Initializer = (() => number) & { mutators?: [] };
>Initializer : Symbol(Initializer, Decl(callableWeakMetadataCallSuggestion.ts, 0, 0))
>mutators : Symbol(mutators, Decl(callableWeakMetadataCallSuggestion.ts, 0, 37))
declare function createStore(initializer: Initializer): void;
>createStore : Symbol(createStore, Decl(callableWeakMetadataCallSuggestion.ts, 0, 54))
>initializer : Symbol(initializer, Decl(callableWeakMetadataCallSuggestion.ts, 2, 29))
>Initializer : Symbol(Initializer, Decl(callableWeakMetadataCallSuggestion.ts, 0, 0))
declare const initializer: () => any;
>initializer : Symbol(initializer, Decl(callableWeakMetadataCallSuggestion.ts, 3, 13))
createStore(initializer);
>createStore : Symbol(createStore, Decl(callableWeakMetadataCallSuggestion.ts, 0, 54))
>initializer : Symbol(initializer, Decl(callableWeakMetadataCallSuggestion.ts, 3, 13))
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/callableWeakMetadataCallSuggestion.ts] ////
=== callableWeakMetadataCallSuggestion.ts ===
type Initializer = (() => number) & { mutators?: [] };
>Initializer : Initializer
>mutators : [] | undefined
declare function createStore(initializer: Initializer): void;
>createStore : (initializer: Initializer) => void
>initializer : Initializer
declare const initializer: () => any;
>initializer : () => any
createStore(initializer);
>createStore(initializer) : void
>createStore : (initializer: Initializer) => void
>initializer : () => any
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/callbackAssignedNonNull.ts] ////
=== callbackAssignedNonNull.ts ===
declare function initialize(callback: (cancel: () => void) => void): void;
>initialize : Symbol(initialize, Decl(callbackAssignedNonNull.ts, 0, 0))
>callback : Symbol(callback, Decl(callbackAssignedNonNull.ts, 0, 28))
>cancel : Symbol(cancel, Decl(callbackAssignedNonNull.ts, 0, 39))
function start() {
>start : Symbol(start, Decl(callbackAssignedNonNull.ts, 0, 74))
let cancel;
>cancel : Symbol(cancel, Decl(callbackAssignedNonNull.ts, 3, 7))
initialize(value => {
>initialize : Symbol(initialize, Decl(callbackAssignedNonNull.ts, 0, 0))
>value : Symbol(value, Decl(callbackAssignedNonNull.ts, 4, 15))
cancel = value;
>cancel : Symbol(cancel, Decl(callbackAssignedNonNull.ts, 3, 7))
>value : Symbol(value, Decl(callbackAssignedNonNull.ts, 4, 15))
});
cancel!();
>cancel : Symbol(cancel, Decl(callbackAssignedNonNull.ts, 3, 7))
}
@@ -0,0 +1,32 @@
//// [tests/cases/compiler/callbackAssignedNonNull.ts] ////
=== callbackAssignedNonNull.ts ===
declare function initialize(callback: (cancel: () => void) => void): void;
>initialize : (callback: (cancel: () => void) => void) => void
>callback : (cancel: () => void) => void
>cancel : () => void
function start() {
>start : () => void
let cancel;
>cancel : any
initialize(value => {
>initialize(value => { cancel = value; }) : void
>initialize : (callback: (cancel: () => void) => void) => void
>value => { cancel = value; } : (value: () => void) => void
>value : () => void
cancel = value;
>cancel = value : () => void
>cancel : any
>value : () => void
});
cancel!();
>cancel!() : any
>cancel! : any
>cancel : any
}
@@ -0,0 +1,18 @@
//// [tests/cases/compiler/chainedFilterPredicateInference.ts] ////
//// [chainedFilterPredicateInference.ts]
declare const items: { id: number }[];
declare const registry: { [id: number]: { [frame: number]: unknown } };
items
.filter(item => true)
.filter(item => !registry[item.id])
.forEach(item => item.id);
//// [chainedFilterPredicateInference.js]
"use strict";
items
.filter(item => true)
.filter(item => !registry[item.id])
.forEach(item => item.id);
@@ -0,0 +1,37 @@
//// [tests/cases/compiler/chainedFilterPredicateInference.ts] ////
=== chainedFilterPredicateInference.ts ===
declare const items: { id: number }[];
>items : Symbol(items, Decl(chainedFilterPredicateInference.ts, 0, 13))
>id : Symbol(id, Decl(chainedFilterPredicateInference.ts, 0, 22))
declare const registry: { [id: number]: { [frame: number]: unknown } };
>registry : Symbol(registry, Decl(chainedFilterPredicateInference.ts, 1, 13))
>id : Symbol(id, Decl(chainedFilterPredicateInference.ts, 1, 27))
>frame : Symbol(frame, Decl(chainedFilterPredicateInference.ts, 1, 43))
items
>items .filter(item => true) .filter(item => !registry[item.id]) .forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
>items .filter(item => true) .filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>items .filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>items : Symbol(items, Decl(chainedFilterPredicateInference.ts, 0, 13))
.filter(item => true)
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>item : Symbol(item, Decl(chainedFilterPredicateInference.ts, 4, 12))
.filter(item => !registry[item.id])
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>item : Symbol(item, Decl(chainedFilterPredicateInference.ts, 5, 12))
>registry : Symbol(registry, Decl(chainedFilterPredicateInference.ts, 1, 13))
>item.id : Symbol(id, Decl(chainedFilterPredicateInference.ts, 0, 22))
>item : Symbol(item, Decl(chainedFilterPredicateInference.ts, 5, 12))
>id : Symbol(id, Decl(chainedFilterPredicateInference.ts, 0, 22))
.forEach(item => item.id);
>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
>item : Symbol(item, Decl(chainedFilterPredicateInference.ts, 6, 13))
>item.id : Symbol(id, Decl(chainedFilterPredicateInference.ts, 0, 22))
>item : Symbol(item, Decl(chainedFilterPredicateInference.ts, 6, 13))
>id : Symbol(id, Decl(chainedFilterPredicateInference.ts, 0, 22))
@@ -0,0 +1,46 @@
//// [tests/cases/compiler/chainedFilterPredicateInference.ts] ////
=== chainedFilterPredicateInference.ts ===
declare const items: { id: number }[];
>items : { id: number; }[]
>id : number
declare const registry: { [id: number]: { [frame: number]: unknown } };
>registry : { [id: number]: { [frame: number]: unknown; }; }
>id : number
>frame : number
items
>items .filter(item => true) .filter(item => !registry[item.id]) .forEach(item => item.id) : void
>items .filter(item => true) .filter(item => !registry[item.id]) .forEach : (callbackfn: (value: { id: number; }, index: number, array: { id: number; }[]) => void, thisArg?: any) => void
>items .filter(item => true) .filter(item => !registry[item.id]) : { id: number; }[]
>items .filter(item => true) .filter : { <S extends { id: number; }>(predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => unknown, thisArg?: any): { id: number; }[]; }
>items .filter(item => true) : { id: number; }[]
>items .filter : { <S extends { id: number; }>(predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => unknown, thisArg?: any): { id: number; }[]; }
>items : { id: number; }[]
.filter(item => true)
>filter : { <S extends { id: number; }>(predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => unknown, thisArg?: any): { id: number; }[]; }
>item => true : (item: { id: number; }) => true
>item : { id: number; }
>true : true
.filter(item => !registry[item.id])
>filter : { <S extends { id: number; }>(predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { id: number; }, index: number, array: { id: number; }[]) => unknown, thisArg?: any): { id: number; }[]; }
>item => !registry[item.id] : (item: { id: number; }) => false
>item : { id: number; }
>!registry[item.id] : false
>registry[item.id] : { [frame: number]: unknown; }
>registry : { [id: number]: { [frame: number]: unknown; }; }
>item.id : number
>item : { id: number; }
>id : number
.forEach(item => item.id);
>forEach : (callbackfn: (value: { id: number; }, index: number, array: { id: number; }[]) => void, thisArg?: any) => void
>item => item.id : (item: { id: number; }) => number
>item : { id: number; }
>item.id : number
>item : { id: number; }
>id : number
@@ -0,0 +1,51 @@
//// [tests/cases/compiler/componentEnhancerReturn.ts] ////
=== componentEnhancerReturn.ts ===
type Component = ((props: number) => number) | (new (props: number) => object);
>Component : Symbol(Component, Decl(componentEnhancerReturn.ts, 0, 0))
>props : Symbol(props, Decl(componentEnhancerReturn.ts, 0, 19))
>props : Symbol(props, Decl(componentEnhancerReturn.ts, 0, 53))
type App = Component & { getInitialProps?: () => object };
>App : Symbol(App, Decl(componentEnhancerReturn.ts, 0, 79))
>Component : Symbol(Component, Decl(componentEnhancerReturn.ts, 0, 0))
>getInitialProps : Symbol(getInitialProps, Decl(componentEnhancerReturn.ts, 1, 24))
declare function render(enhance: (app: App) => App): void;
>render : Symbol(render, Decl(componentEnhancerReturn.ts, 1, 58))
>enhance : Symbol(enhance, Decl(componentEnhancerReturn.ts, 2, 24))
>app : Symbol(app, Decl(componentEnhancerReturn.ts, 2, 34))
>App : Symbol(App, Decl(componentEnhancerReturn.ts, 0, 79))
>App : Symbol(App, Decl(componentEnhancerReturn.ts, 0, 79))
render(app => props => props);
>render : Symbol(render, Decl(componentEnhancerReturn.ts, 1, 58))
>app : Symbol(app, Decl(componentEnhancerReturn.ts, 3, 7))
>props : Symbol(props, Decl(componentEnhancerReturn.ts, 3, 13))
>props : Symbol(props, Decl(componentEnhancerReturn.ts, 3, 13))
interface RenderPlugin { enhance(app: Component): (props: number) => number }
>RenderPlugin : Symbol(RenderPlugin, Decl(componentEnhancerReturn.ts, 3, 30))
>enhance : Symbol(RenderPlugin.enhance, Decl(componentEnhancerReturn.ts, 5, 24))
>app : Symbol(app, Decl(componentEnhancerReturn.ts, 5, 33))
>Component : Symbol(Component, Decl(componentEnhancerReturn.ts, 0, 0))
>props : Symbol(props, Decl(componentEnhancerReturn.ts, 5, 51))
declare const plugins: RenderPlugin[];
>plugins : Symbol(plugins, Decl(componentEnhancerReturn.ts, 6, 13))
>RenderPlugin : Symbol(RenderPlugin, Decl(componentEnhancerReturn.ts, 3, 30))
render(app => plugins.reduce((result, plugin) => plugin.enhance(result), app));
>render : Symbol(render, Decl(componentEnhancerReturn.ts, 1, 58))
>app : Symbol(app, Decl(componentEnhancerReturn.ts, 7, 7))
>plugins.reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>plugins : Symbol(plugins, Decl(componentEnhancerReturn.ts, 6, 13))
>reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>result : Symbol(result, Decl(componentEnhancerReturn.ts, 7, 30))
>plugin : Symbol(plugin, Decl(componentEnhancerReturn.ts, 7, 37))
>plugin.enhance : Symbol(RenderPlugin.enhance, Decl(componentEnhancerReturn.ts, 5, 24))
>plugin : Symbol(plugin, Decl(componentEnhancerReturn.ts, 7, 37))
>enhance : Symbol(RenderPlugin.enhance, Decl(componentEnhancerReturn.ts, 5, 24))
>result : Symbol(result, Decl(componentEnhancerReturn.ts, 7, 30))
>app : Symbol(app, Decl(componentEnhancerReturn.ts, 7, 7))
@@ -0,0 +1,53 @@
//// [tests/cases/compiler/componentEnhancerReturn.ts] ////
=== componentEnhancerReturn.ts ===
type Component = ((props: number) => number) | (new (props: number) => object);
>Component : Component
>props : number
>props : number
type App = Component & { getInitialProps?: () => object };
>App : App
>getInitialProps : (() => object) | undefined
declare function render(enhance: (app: App) => App): void;
>render : (enhance: (app: App) => App) => void
>enhance : (app: App) => App
>app : App
render(app => props => props);
>render(app => props => props) : void
>render : (enhance: (app: App) => App) => void
>app => props => props : (app: App) => (props: number) => number
>app : App
>props => props : (props: number) => number
>props : number
>props : number
interface RenderPlugin { enhance(app: Component): (props: number) => number }
>enhance : (app: Component) => (props: number) => number
>app : Component
>props : number
declare const plugins: RenderPlugin[];
>plugins : RenderPlugin[]
render(app => plugins.reduce((result, plugin) => plugin.enhance(result), app));
>render(app => plugins.reduce((result, plugin) => plugin.enhance(result), app)) : void
>render : (enhance: (app: App) => App) => void
>app => plugins.reduce((result, plugin) => plugin.enhance(result), app) : (app: App) => App
>app : App
>plugins.reduce((result, plugin) => plugin.enhance(result), app) : App
>plugins.reduce : { (callbackfn: (previousValue: RenderPlugin, currentValue: RenderPlugin, currentIndex: number, array: RenderPlugin[]) => RenderPlugin): RenderPlugin; (callbackfn: (previousValue: RenderPlugin, currentValue: RenderPlugin, currentIndex: number, array: RenderPlugin[]) => RenderPlugin, initialValue: RenderPlugin): RenderPlugin; <U>(callbackfn: (previousValue: U, currentValue: RenderPlugin, currentIndex: number, array: RenderPlugin[]) => U, initialValue: U): U; }
>plugins : RenderPlugin[]
>reduce : { (callbackfn: (previousValue: RenderPlugin, currentValue: RenderPlugin, currentIndex: number, array: RenderPlugin[]) => RenderPlugin): RenderPlugin; (callbackfn: (previousValue: RenderPlugin, currentValue: RenderPlugin, currentIndex: number, array: RenderPlugin[]) => RenderPlugin, initialValue: RenderPlugin): RenderPlugin; <U>(callbackfn: (previousValue: U, currentValue: RenderPlugin, currentIndex: number, array: RenderPlugin[]) => U, initialValue: U): U; }
>(result, plugin) => plugin.enhance(result) : (result: App, plugin: RenderPlugin) => (props: number) => number
>result : App
>plugin : RenderPlugin
>plugin.enhance(result) : (props: number) => number
>plugin.enhance : (app: Component) => (props: number) => number
>plugin : RenderPlugin
>enhance : (app: Component) => (props: number) => number
>result : App
>app : App
@@ -0,0 +1,17 @@
//// [tests/cases/compiler/compoundAssignmentAfterExcludedLiteral.ts] ////
//// [compoundAssignmentAfterExcludedLiteral.ts]
function append(buffer: { value: string }) {
if (buffer.value !== "") {
buffer.value += "\n";
}
}
//// [compoundAssignmentAfterExcludedLiteral.js]
"use strict";
function append(buffer) {
if (buffer.value !== "") {
buffer.value += "\n";
}
}
@@ -0,0 +1,20 @@
//// [tests/cases/compiler/compoundAssignmentAfterExcludedLiteral.ts] ////
=== compoundAssignmentAfterExcludedLiteral.ts ===
function append(buffer: { value: string }) {
>append : Symbol(append, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 0))
>buffer : Symbol(buffer, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 16))
>value : Symbol(value, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 25))
if (buffer.value !== "") {
>buffer.value : Symbol(value, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 25))
>buffer : Symbol(buffer, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 16))
>value : Symbol(value, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 25))
buffer.value += "\n";
>buffer.value : Symbol(value, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 25))
>buffer : Symbol(buffer, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 16))
>value : Symbol(value, Decl(compoundAssignmentAfterExcludedLiteral.ts, 0, 25))
}
}
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/compoundAssignmentAfterExcludedLiteral.ts] ////
=== compoundAssignmentAfterExcludedLiteral.ts ===
function append(buffer: { value: string }) {
>append : (buffer: { value: string; }) => void
>buffer : { value: string; }
>value : string
if (buffer.value !== "") {
>buffer.value !== "" : boolean
>buffer.value : string
>buffer : { value: string; }
>value : string
>"" : ""
buffer.value += "\n";
>buffer.value += "\n" : string
>buffer.value : string
>buffer : { value: string; }
>value : string
>"\n" : "\n"
}
}
@@ -0,0 +1,13 @@
//// [tests/cases/compiler/conditionalExportsNodeTypesFallback.ts] ////
=== /index.mts ===
import { value } from "provider";
>value : Symbol(value, Decl(index.mts, 0, 8))
value;
>value : Symbol(value, Decl(index.mts, 0, 8))
=== /node_modules/provider/types.d.ts ===
export const value: number;
>value : Symbol(value, Decl(types.d.ts, 0, 12))
@@ -0,0 +1,22 @@
======== Resolving module 'provider' from '/index.mts'. ========
Explicitly specified module resolution kind: 'NodeNext'.
Resolving in ESM mode with conditions 'import', 'types', 'node'.
File '/package.json' does not exist.
Loading module 'provider' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Found 'package.json' at '/node_modules/provider/package.json'.
Entering conditional exports.
Matched 'exports' condition 'node'.
Using 'exports' subpath '.' with target './index.js'.
File name '/node_modules/provider/index.js' has a '.js' extension - stripping it.
File '/node_modules/provider/index.ts' does not exist.
File '/node_modules/provider/index.tsx' does not exist.
File '/node_modules/provider/index.d.ts' does not exist.
Failed to resolve under condition 'node'.
Matched 'exports' condition 'types'.
Using 'exports' subpath '.' with target './types.d.ts'.
File '/node_modules/provider/types.d.ts' exists - use it as a name resolution result.
Resolved under condition 'types'.
Exiting conditional exports.
Resolving real path for '/node_modules/provider/types.d.ts', result '/node_modules/provider/types.d.ts'.
======== Module name 'provider' was successfully resolved to '/node_modules/provider/types.d.ts'. ========
@@ -0,0 +1,13 @@
//// [tests/cases/compiler/conditionalExportsNodeTypesFallback.ts] ////
=== /index.mts ===
import { value } from "provider";
>value : number
value;
>value : number
=== /node_modules/provider/types.d.ts ===
export const value: number;
>value : number
@@ -0,0 +1,13 @@
//// [tests/cases/compiler/conditionalExportsRequireTypesFallback.ts] ////
=== /index.cts ===
import { value } from "provider";
>value : Symbol(value, Decl(index.cts, 0, 8))
value;
>value : Symbol(value, Decl(index.cts, 0, 8))
=== /node_modules/provider/index.d.ts ===
export const value: number;
>value : Symbol(value, Decl(index.d.ts, 0, 12))
@@ -0,0 +1,21 @@
======== Resolving module 'provider' from '/index.cts'. ========
Explicitly specified module resolution kind: 'NodeNext'.
Resolving in CJS mode with conditions 'require', 'types', 'node'.
File '/package.json' does not exist.
Loading module 'provider' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Found 'package.json' at '/node_modules/provider/package.json'.
Entering conditional exports.
Matched 'exports' condition 'require'.
Using 'exports' subpath '.' with target './index.cjs'.
File name '/node_modules/provider/index.cjs' has a '.cjs' extension - stripping it.
File '/node_modules/provider/index.cts' does not exist.
File '/node_modules/provider/index.d.cts' does not exist.
Failed to resolve under condition 'require'.
Matched 'exports' condition 'types'.
Using 'exports' subpath '.' with target './index.d.ts'.
File '/node_modules/provider/index.d.ts' exists - use it as a name resolution result.
Resolved under condition 'types'.
Exiting conditional exports.
Resolving real path for '/node_modules/provider/index.d.ts', result '/node_modules/provider/index.d.ts'.
======== Module name 'provider' was successfully resolved to '/node_modules/provider/index.d.ts'. ========
@@ -0,0 +1,13 @@
//// [tests/cases/compiler/conditionalExportsRequireTypesFallback.ts] ////
=== /index.cts ===
import { value } from "provider";
>value : number
value;
>value : number
=== /node_modules/provider/index.d.ts ===
export const value: number;
>value : number
@@ -0,0 +1,16 @@
//// [tests/cases/compiler/conditionalExportsTypesImportFallback.ts] ////
=== /index.mts ===
import color from "theme/tokens";
>color : Symbol(color, Decl(index.mts, 0, 6))
color;
>color : Symbol(color, Decl(index.mts, 0, 6))
=== /node_modules/theme/tokens.d.mts ===
declare const color: string;
>color : Symbol(color, Decl(tokens.d.mts, 0, 13))
export default color;
>color : Symbol(color, Decl(tokens.d.mts, 0, 13))
@@ -0,0 +1,21 @@
======== Resolving module 'theme/tokens' from '/index.mts'. ========
Explicitly specified module resolution kind: 'Bundler'.
Resolving in CJS mode with conditions 'import', 'types'.
File '/package.json' does not exist.
Loading module 'theme/tokens' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Found 'package.json' at '/node_modules/theme/package.json'.
Entering conditional exports.
Matched 'exports' condition 'types'.
Using 'exports' subpath './tokens' with target './tokens.d.ts'.
File '/node_modules/theme/tokens.d.ts' does not exist.
Failed to resolve under condition 'types'.
Matched 'exports' condition 'import'.
Using 'exports' subpath './tokens' with target './tokens.mjs'.
File name '/node_modules/theme/tokens.mjs' has a '.mjs' extension - stripping it.
File '/node_modules/theme/tokens.mts' does not exist.
File '/node_modules/theme/tokens.d.mts' exists - use it as a name resolution result.
Resolved under condition 'import'.
Exiting conditional exports.
Resolving real path for '/node_modules/theme/tokens.d.mts', result '/node_modules/theme/tokens.d.mts'.
======== Module name 'theme/tokens' was successfully resolved to '/node_modules/theme/tokens.d.mts'. ========
@@ -0,0 +1,16 @@
//// [tests/cases/compiler/conditionalExportsTypesImportFallback.ts] ////
=== /index.mts ===
import color from "theme/tokens";
>color : string
color;
>color : string
=== /node_modules/theme/tokens.d.mts ===
declare const color: string;
>color : string
export default color;
>color : string
@@ -0,0 +1,35 @@
//// [tests/cases/compiler/conditionalFunctionUnionInference.ts] ////
=== conditionalFunctionUnionInference.ts ===
type DeepValue<T> = T extends () => unknown ? T :
>DeepValue : Symbol(DeepValue, Decl(conditionalFunctionUnionInference.ts, 0, 0))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 0, 15))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 0, 15))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 0, 15))
{ [K in keyof T]: DeepValue<T[K]> };
>K : Symbol(K, Decl(conditionalFunctionUnionInference.ts, 1, 7))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 0, 15))
>DeepValue : Symbol(DeepValue, Decl(conditionalFunctionUnionInference.ts, 0, 0))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 0, 15))
>K : Symbol(K, Decl(conditionalFunctionUnionInference.ts, 1, 7))
declare function createValue<T>(initialValue: DeepValue<T | (() => T)>): T;
>createValue : Symbol(createValue, Decl(conditionalFunctionUnionInference.ts, 1, 40))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 3, 29))
>initialValue : Symbol(initialValue, Decl(conditionalFunctionUnionInference.ts, 3, 32))
>DeepValue : Symbol(DeepValue, Decl(conditionalFunctionUnionInference.ts, 0, 0))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 3, 29))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 3, 29))
>T : Symbol(T, Decl(conditionalFunctionUnionInference.ts, 3, 29))
const value = createValue(() => ({ ready: true }));
>value : Symbol(value, Decl(conditionalFunctionUnionInference.ts, 5, 5))
>createValue : Symbol(createValue, Decl(conditionalFunctionUnionInference.ts, 1, 40))
>ready : Symbol(ready, Decl(conditionalFunctionUnionInference.ts, 5, 34))
value.ready;
>value.ready : Symbol(ready, Decl(conditionalFunctionUnionInference.ts, 5, 34))
>value : Symbol(value, Decl(conditionalFunctionUnionInference.ts, 5, 5))
>ready : Symbol(ready, Decl(conditionalFunctionUnionInference.ts, 5, 34))
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/conditionalFunctionUnionInference.ts] ////
=== conditionalFunctionUnionInference.ts ===
type DeepValue<T> = T extends () => unknown ? T :
>DeepValue : DeepValue<T>
{ [K in keyof T]: DeepValue<T[K]> };
declare function createValue<T>(initialValue: DeepValue<T | (() => T)>): T;
>createValue : <T>(initialValue: DeepValue<T | (() => T)>) => T
>initialValue : (() => T) | DeepValue<T>
const value = createValue(() => ({ ready: true }));
>value : { ready: boolean; }
>createValue(() => ({ ready: true })) : { ready: boolean; }
>createValue : <T>(initialValue: DeepValue<T | (() => T)>) => T
>() => ({ ready: true }) : () => { ready: boolean; }
>({ ready: true }) : { ready: true; }
>{ ready: true } : { ready: true; }
>ready : true
>true : true
value.ready;
>value.ready : boolean
>value : { ready: boolean; }
>ready : boolean
@@ -0,0 +1,48 @@
//// [tests/cases/compiler/conditionalPromptInference.ts] ////
=== conditionalPromptInference.ts ===
declare function createPrompt<Value, Config>(
>createPrompt : Symbol(createPrompt, Decl(conditionalPromptInference.ts, 0, 0))
>Value : Symbol(Value, Decl(conditionalPromptInference.ts, 0, 30))
>Config : Symbol(Config, Decl(conditionalPromptInference.ts, 0, 36))
view: (config: Config, done: (value: Value) => void) => void,
>view : Symbol(view, Decl(conditionalPromptInference.ts, 0, 45))
>config : Symbol(config, Decl(conditionalPromptInference.ts, 1, 11))
>Config : Symbol(Config, Decl(conditionalPromptInference.ts, 0, 36))
>done : Symbol(done, Decl(conditionalPromptInference.ts, 1, 26))
>value : Symbol(value, Decl(conditionalPromptInference.ts, 1, 34))
>Value : Symbol(Value, Decl(conditionalPromptInference.ts, 0, 30))
): (config: Config) => Value;
>config : Symbol(config, Decl(conditionalPromptInference.ts, 2, 4))
>Config : Symbol(Config, Decl(conditionalPromptInference.ts, 0, 36))
>Value : Symbol(Value, Decl(conditionalPromptInference.ts, 0, 30))
const numberPrompt = createPrompt(<Required extends boolean>(
>numberPrompt : Symbol(numberPrompt, Decl(conditionalPromptInference.ts, 4, 5))
>createPrompt : Symbol(createPrompt, Decl(conditionalPromptInference.ts, 0, 0))
>Required : Symbol(Required, Decl(conditionalPromptInference.ts, 4, 35))
config: { required?: Required },
>config : Symbol(config, Decl(conditionalPromptInference.ts, 4, 61))
>required : Symbol(required, Decl(conditionalPromptInference.ts, 5, 13))
>Required : Symbol(Required, Decl(conditionalPromptInference.ts, 4, 35))
done: (value: Required extends true ? number : number | undefined) => void,
>done : Symbol(done, Decl(conditionalPromptInference.ts, 5, 36))
>value : Symbol(value, Decl(conditionalPromptInference.ts, 6, 11))
>Required : Symbol(Required, Decl(conditionalPromptInference.ts, 4, 35))
) => {});
const required: number = numberPrompt<true>({ required: true });
>required : Symbol(required, Decl(conditionalPromptInference.ts, 9, 5))
>numberPrompt : Symbol(numberPrompt, Decl(conditionalPromptInference.ts, 4, 5))
>required : Symbol(required, Decl(conditionalPromptInference.ts, 9, 45))
const optional: number | undefined = numberPrompt<false>({ required: false });
>optional : Symbol(optional, Decl(conditionalPromptInference.ts, 10, 5))
>numberPrompt : Symbol(numberPrompt, Decl(conditionalPromptInference.ts, 4, 5))
>required : Symbol(required, Decl(conditionalPromptInference.ts, 10, 58))
@@ -0,0 +1,50 @@
//// [tests/cases/compiler/conditionalPromptInference.ts] ////
=== conditionalPromptInference.ts ===
declare function createPrompt<Value, Config>(
>createPrompt : <Value, Config>(view: (config: Config, done: (value: Value) => void) => void) => (config: Config) => Value
view: (config: Config, done: (value: Value) => void) => void,
>view : (config: Config, done: (value: Value) => void) => void
>config : Config
>done : (value: Value) => void
>value : Value
): (config: Config) => Value;
>config : Config
const numberPrompt = createPrompt(<Required extends boolean>(
>numberPrompt : <Required extends boolean>(config: { required?: Required; }) => Required extends true ? number : number | undefined
>createPrompt(<Required extends boolean>( config: { required?: Required }, done: (value: Required extends true ? number : number | undefined) => void,) => {}) : <Required extends boolean>(config: { required?: Required; }) => Required extends true ? number : number | undefined
>createPrompt : <Value, Config>(view: (config: Config, done: (value: Value) => void) => void) => (config: Config) => Value
><Required extends boolean>( config: { required?: Required }, done: (value: Required extends true ? number : number | undefined) => void,) => {} : <Required extends boolean>(config: { required?: Required; }, done: (value: Required extends true ? number : number | undefined) => void) => void
config: { required?: Required },
>config : { required?: Required; }
>required : Required | undefined
done: (value: Required extends true ? number : number | undefined) => void,
>done : (value: Required extends true ? number : number | undefined) => void
>value : Required extends true ? number : number | undefined
>true : true
) => {});
const required: number = numberPrompt<true>({ required: true });
>required : number
>numberPrompt<true>({ required: true }) : number
>numberPrompt : <Required extends boolean>(config: { required?: Required; }) => Required extends true ? number : number | undefined
>true : true
>{ required: true } : { required: true; }
>required : true
>true : true
const optional: number | undefined = numberPrompt<false>({ required: false });
>optional : number | undefined
>numberPrompt<false>({ required: false }) : number | undefined
>numberPrompt : <Required extends boolean>(config: { required?: Required; }) => Required extends true ? number : number | undefined
>false : false
>{ required: false } : { required: false; }
>required : false
>false : false
@@ -0,0 +1,37 @@
//// [tests/cases/compiler/contextualFactoryReturnToOptionalClassField.ts] ////
=== contextualFactoryReturnToOptionalClassField.ts ===
class Reply<T extends string | number> { value!: T; }
>Reply : Symbol(Reply, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 0))
>T : Symbol(T, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 12))
>value : Symbol(Reply.value, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 40))
>T : Symbol(T, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 12))
declare function create<Ctor extends new () => unknown, R extends InstanceType<Ctor>>(ctor: Ctor): R;
>create : Symbol(create, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 53))
>Ctor : Symbol(Ctor, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 24))
>R : Symbol(R, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 55))
>InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
>Ctor : Symbol(Ctor, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 24))
>ctor : Symbol(ctor, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 86))
>Ctor : Symbol(Ctor, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 24))
>R : Symbol(R, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 55))
class Container<T extends string | number> {
>Container : Symbol(Container, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 101))
>T : Symbol(T, Decl(contextualFactoryReturnToOptionalClassField.ts, 2, 16))
item?: Reply<T>;
>item : Symbol(Container.item, Decl(contextualFactoryReturnToOptionalClassField.ts, 2, 44))
>Reply : Symbol(Reply, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 0))
>T : Symbol(T, Decl(contextualFactoryReturnToOptionalClassField.ts, 2, 16))
initialize() { this.item = create(Reply); }
>initialize : Symbol(Container.initialize, Decl(contextualFactoryReturnToOptionalClassField.ts, 3, 20))
>this.item : Symbol(Container.item, Decl(contextualFactoryReturnToOptionalClassField.ts, 2, 44))
>this : Symbol(Container, Decl(contextualFactoryReturnToOptionalClassField.ts, 1, 101))
>item : Symbol(Container.item, Decl(contextualFactoryReturnToOptionalClassField.ts, 2, 44))
>create : Symbol(create, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 53))
>Reply : Symbol(Reply, Decl(contextualFactoryReturnToOptionalClassField.ts, 0, 0))
}
@@ -0,0 +1,28 @@
//// [tests/cases/compiler/contextualFactoryReturnToOptionalClassField.ts] ////
=== contextualFactoryReturnToOptionalClassField.ts ===
class Reply<T extends string | number> { value!: T; }
>Reply : Reply<T>
>value : T
declare function create<Ctor extends new () => unknown, R extends InstanceType<Ctor>>(ctor: Ctor): R;
>create : <Ctor extends new () => unknown, R extends InstanceType<Ctor>>(ctor: Ctor) => R
>ctor : Ctor
class Container<T extends string | number> {
>Container : Container<T>
item?: Reply<T>;
>item : Reply<T> | undefined
initialize() { this.item = create(Reply); }
>initialize : () => void
>this.item = create(Reply) : Reply<T>
>this.item : Reply<T> | undefined
>this : this
>item : Reply<T> | undefined
>create(Reply) : Reply<T>
>create : <Ctor extends new () => unknown, R extends InstanceType<Ctor>>(ctor: Ctor) => R
>Reply : typeof Reply
}
@@ -0,0 +1,36 @@
//// [tests/cases/compiler/contextualGenericReturnToOptionalClassField.ts] ////
=== contextualGenericReturnToOptionalClassField.ts ===
declare function lookup<T extends object = object>(): T;
>lookup : Symbol(lookup, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 0))
>T : Symbol(T, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 24))
>T : Symbol(T, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 24))
class Container {
>Container : Symbol(Container, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 56))
item?: { label: string };
>item : Symbol(Container.item, Decl(contextualGenericReturnToOptionalClassField.ts, 1, 17))
>label : Symbol(label, Decl(contextualGenericReturnToOptionalClassField.ts, 2, 12))
getLabel() {
>getLabel : Symbol(Container.getLabel, Decl(contextualGenericReturnToOptionalClassField.ts, 2, 29))
if (!this.item) this.item = lookup();
>this.item : Symbol(Container.item, Decl(contextualGenericReturnToOptionalClassField.ts, 1, 17))
>this : Symbol(Container, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 56))
>item : Symbol(Container.item, Decl(contextualGenericReturnToOptionalClassField.ts, 1, 17))
>this.item : Symbol(Container.item, Decl(contextualGenericReturnToOptionalClassField.ts, 1, 17))
>this : Symbol(Container, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 56))
>item : Symbol(Container.item, Decl(contextualGenericReturnToOptionalClassField.ts, 1, 17))
>lookup : Symbol(lookup, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 0))
return this.item.label;
>this.item.label : Symbol(label, Decl(contextualGenericReturnToOptionalClassField.ts, 2, 12))
>this.item : Symbol(Container.item, Decl(contextualGenericReturnToOptionalClassField.ts, 1, 17))
>this : Symbol(Container, Decl(contextualGenericReturnToOptionalClassField.ts, 0, 56))
>item : Symbol(Container.item, Decl(contextualGenericReturnToOptionalClassField.ts, 1, 17))
>label : Symbol(label, Decl(contextualGenericReturnToOptionalClassField.ts, 2, 12))
}
}
@@ -0,0 +1,37 @@
//// [tests/cases/compiler/contextualGenericReturnToOptionalClassField.ts] ////
=== contextualGenericReturnToOptionalClassField.ts ===
declare function lookup<T extends object = object>(): T;
>lookup : <T extends object = object>() => T
class Container {
>Container : Container
item?: { label: string };
>item : { label: string; } | undefined
>label : string
getLabel() {
>getLabel : () => string
if (!this.item) this.item = lookup();
>!this.item : boolean
>this.item : { label: string; } | undefined
>this : this
>item : { label: string; } | undefined
>this.item = lookup() : { label: string; }
>this.item : { label: string; } | undefined
>this : this
>item : { label: string; } | undefined
>lookup() : { label: string; }
>lookup : <T extends object = object>() => T
return this.item.label;
>this.item.label : string
>this.item : { label: string; }
>this : this
>item : { label: string; }
>label : string
}
}
@@ -0,0 +1,32 @@
//// [tests/cases/compiler/contextualReturnArrayPatternCallback.ts] ////
//// [contextualReturnArrayPatternCallback.ts]
interface Matcher<Input, Value = unknown> {
matcher(): { match(value: Input): boolean; value?: Value };
}
type Pattern<Input> = Input | Matcher<Input> | { [Key in keyof Input]?: Pattern<Input[Key]> };
type ArrayElement<Input> = Input extends readonly (infer Value)[] ? Value : unknown;
declare function array<Input, Value extends Pattern<ArrayElement<Input>>>(value: Value): Matcher<Input, Value>;
declare function when<Input, Callback extends (value: Input) => unknown>(callback: Callback): Matcher<Input>;
declare function accept<Value extends Pattern<{ list: { prop: string }[] }>>(value: Value): void;
accept({
list: array({
prop: when(value => {
const text: string = value;
return true;
}),
}),
});
//// [contextualReturnArrayPatternCallback.js]
"use strict";
accept({
list: array({
prop: when(value => {
const text = value;
return true;
}),
}),
});
@@ -0,0 +1,89 @@
//// [tests/cases/compiler/contextualReturnArrayPatternCallback.ts] ////
=== contextualReturnArrayPatternCallback.ts ===
interface Matcher<Input, Value = unknown> {
>Matcher : Symbol(Matcher, Decl(contextualReturnArrayPatternCallback.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 0, 18))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 0, 24))
matcher(): { match(value: Input): boolean; value?: Value };
>matcher : Symbol(Matcher.matcher, Decl(contextualReturnArrayPatternCallback.ts, 0, 43))
>match : Symbol(match, Decl(contextualReturnArrayPatternCallback.ts, 1, 16))
>value : Symbol(value, Decl(contextualReturnArrayPatternCallback.ts, 1, 23))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 0, 18))
>value : Symbol(value, Decl(contextualReturnArrayPatternCallback.ts, 1, 46))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 0, 24))
}
type Pattern<Input> = Input | Matcher<Input> | { [Key in keyof Input]?: Pattern<Input[Key]> };
>Pattern : Symbol(Pattern, Decl(contextualReturnArrayPatternCallback.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 3, 13))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 3, 13))
>Matcher : Symbol(Matcher, Decl(contextualReturnArrayPatternCallback.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 3, 13))
>Key : Symbol(Key, Decl(contextualReturnArrayPatternCallback.ts, 3, 50))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 3, 13))
>Pattern : Symbol(Pattern, Decl(contextualReturnArrayPatternCallback.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 3, 13))
>Key : Symbol(Key, Decl(contextualReturnArrayPatternCallback.ts, 3, 50))
type ArrayElement<Input> = Input extends readonly (infer Value)[] ? Value : unknown;
>ArrayElement : Symbol(ArrayElement, Decl(contextualReturnArrayPatternCallback.ts, 3, 94))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 4, 18))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 4, 18))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 4, 56))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 4, 56))
declare function array<Input, Value extends Pattern<ArrayElement<Input>>>(value: Value): Matcher<Input, Value>;
>array : Symbol(array, Decl(contextualReturnArrayPatternCallback.ts, 4, 84))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 5, 23))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 5, 29))
>Pattern : Symbol(Pattern, Decl(contextualReturnArrayPatternCallback.ts, 2, 1))
>ArrayElement : Symbol(ArrayElement, Decl(contextualReturnArrayPatternCallback.ts, 3, 94))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 5, 23))
>value : Symbol(value, Decl(contextualReturnArrayPatternCallback.ts, 5, 74))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 5, 29))
>Matcher : Symbol(Matcher, Decl(contextualReturnArrayPatternCallback.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 5, 23))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 5, 29))
declare function when<Input, Callback extends (value: Input) => unknown>(callback: Callback): Matcher<Input>;
>when : Symbol(when, Decl(contextualReturnArrayPatternCallback.ts, 5, 111))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 6, 22))
>Callback : Symbol(Callback, Decl(contextualReturnArrayPatternCallback.ts, 6, 28))
>value : Symbol(value, Decl(contextualReturnArrayPatternCallback.ts, 6, 47))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 6, 22))
>callback : Symbol(callback, Decl(contextualReturnArrayPatternCallback.ts, 6, 73))
>Callback : Symbol(Callback, Decl(contextualReturnArrayPatternCallback.ts, 6, 28))
>Matcher : Symbol(Matcher, Decl(contextualReturnArrayPatternCallback.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnArrayPatternCallback.ts, 6, 22))
declare function accept<Value extends Pattern<{ list: { prop: string }[] }>>(value: Value): void;
>accept : Symbol(accept, Decl(contextualReturnArrayPatternCallback.ts, 6, 109))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 7, 24))
>Pattern : Symbol(Pattern, Decl(contextualReturnArrayPatternCallback.ts, 2, 1))
>list : Symbol(list, Decl(contextualReturnArrayPatternCallback.ts, 7, 47))
>prop : Symbol(prop, Decl(contextualReturnArrayPatternCallback.ts, 7, 55))
>value : Symbol(value, Decl(contextualReturnArrayPatternCallback.ts, 7, 77))
>Value : Symbol(Value, Decl(contextualReturnArrayPatternCallback.ts, 7, 24))
accept({
>accept : Symbol(accept, Decl(contextualReturnArrayPatternCallback.ts, 6, 109))
list: array({
>list : Symbol(list, Decl(contextualReturnArrayPatternCallback.ts, 9, 8))
>array : Symbol(array, Decl(contextualReturnArrayPatternCallback.ts, 4, 84))
prop: when(value => {
>prop : Symbol(prop, Decl(contextualReturnArrayPatternCallback.ts, 10, 17))
>when : Symbol(when, Decl(contextualReturnArrayPatternCallback.ts, 5, 111))
>value : Symbol(value, Decl(contextualReturnArrayPatternCallback.ts, 11, 19))
const text: string = value;
>text : Symbol(text, Decl(contextualReturnArrayPatternCallback.ts, 12, 17))
>value : Symbol(value, Decl(contextualReturnArrayPatternCallback.ts, 11, 19))
return true;
}),
}),
});
@@ -0,0 +1,60 @@
//// [tests/cases/compiler/contextualReturnArrayPatternCallback.ts] ////
=== contextualReturnArrayPatternCallback.ts ===
interface Matcher<Input, Value = unknown> {
matcher(): { match(value: Input): boolean; value?: Value };
>matcher : () => { match(value: Input): boolean; value?: Value; }
>match : (value: Input) => boolean
>value : Input
>value : Value | undefined
}
type Pattern<Input> = Input | Matcher<Input> | { [Key in keyof Input]?: Pattern<Input[Key]> };
>Pattern : Pattern<Input>
type ArrayElement<Input> = Input extends readonly (infer Value)[] ? Value : unknown;
>ArrayElement : ArrayElement<Input>
declare function array<Input, Value extends Pattern<ArrayElement<Input>>>(value: Value): Matcher<Input, Value>;
>array : <Input, Value extends Pattern<ArrayElement<Input>>>(value: Value) => Matcher<Input, Value>
>value : Value
declare function when<Input, Callback extends (value: Input) => unknown>(callback: Callback): Matcher<Input>;
>when : <Input, Callback extends (value: Input) => unknown>(callback: Callback) => Matcher<Input>
>value : Input
>callback : Callback
declare function accept<Value extends Pattern<{ list: { prop: string }[] }>>(value: Value): void;
>accept : <Value extends Pattern<{ list: { prop: string; }[]; }>>(value: Value) => void
>list : { prop: string; }[]
>prop : string
>value : Value
accept({
>accept({ list: array({ prop: when(value => { const text: string = value; return true; }), }),}) : void
>accept : <Value extends Pattern<{ list: { prop: string; }[]; }>>(value: Value) => void
>{ list: array({ prop: when(value => { const text: string = value; return true; }), }),} : { list: Matcher<{ prop: string; }[], { prop: Matcher<string, unknown>; }>; }
list: array({
>list : Matcher<{ prop: string; }[], { prop: Matcher<string, unknown>; }>
>array({ prop: when(value => { const text: string = value; return true; }), }) : Matcher<{ prop: string; }[], { prop: Matcher<string, unknown>; }>
>array : <Input, Value extends Pattern<ArrayElement<Input>>>(value: Value) => Matcher<Input, Value>
>{ prop: when(value => { const text: string = value; return true; }), } : { prop: Matcher<string, unknown>; }
prop: when(value => {
>prop : Matcher<string, unknown>
>when(value => { const text: string = value; return true; }) : Matcher<string, unknown>
>when : <Input, Callback extends (value: Input) => unknown>(callback: Callback) => Matcher<Input>
>value => { const text: string = value; return true; } : (value: string) => boolean
>value : string
const text: string = value;
>text : string
>value : string
return true;
>true : true
}),
}),
});
@@ -0,0 +1,32 @@
//// [tests/cases/compiler/contextualReturnRecursivePatternArguments.ts] ////
//// [contextualReturnRecursivePatternArguments.ts]
interface Matcher<Input, Pattern = unknown> {
matcher(): { match(value: Input): boolean; pattern?: Pattern };
}
type Pattern<Input> = Input | Matcher<Input> | { [Key in keyof Input]?: Pattern<Input[Key]> };
declare function union<Input, Patterns extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...patterns: Patterns): Matcher<Input, Patterns>;
declare function optional<Input, Value extends unknown extends Input ? unknown : Pattern<Input>>(value: Value): Matcher<Input, Value>;
declare function intersection<Input, Values extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...values: Values): Matcher<Input, Values>;
declare function accept<Value extends Pattern<{ type: "a" | "b" }>>(value: Value): void;
accept(optional({
// @ts-expect-error
type: union("oops"),
}));
accept(intersection({
// @ts-expect-error
type: union("oops"),
}));
//// [contextualReturnRecursivePatternArguments.js]
"use strict";
accept(optional({
// @ts-expect-error
type: union("oops"),
}));
accept(intersection({
// @ts-expect-error
type: union("oops"),
}));
@@ -0,0 +1,98 @@
//// [tests/cases/compiler/contextualReturnRecursivePatternArguments.ts] ////
=== contextualReturnRecursivePatternArguments.ts ===
interface Matcher<Input, Pattern = unknown> {
>Matcher : Symbol(Matcher, Decl(contextualReturnRecursivePatternArguments.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 0, 18))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 0, 24))
matcher(): { match(value: Input): boolean; pattern?: Pattern };
>matcher : Symbol(Matcher.matcher, Decl(contextualReturnRecursivePatternArguments.ts, 0, 45))
>match : Symbol(match, Decl(contextualReturnRecursivePatternArguments.ts, 1, 16))
>value : Symbol(value, Decl(contextualReturnRecursivePatternArguments.ts, 1, 23))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 0, 18))
>pattern : Symbol(pattern, Decl(contextualReturnRecursivePatternArguments.ts, 1, 46))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 0, 24))
}
type Pattern<Input> = Input | Matcher<Input> | { [Key in keyof Input]?: Pattern<Input[Key]> };
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 3, 13))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 3, 13))
>Matcher : Symbol(Matcher, Decl(contextualReturnRecursivePatternArguments.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 3, 13))
>Key : Symbol(Key, Decl(contextualReturnRecursivePatternArguments.ts, 3, 50))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 3, 13))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 3, 13))
>Key : Symbol(Key, Decl(contextualReturnRecursivePatternArguments.ts, 3, 50))
declare function union<Input, Patterns extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...patterns: Patterns): Matcher<Input, Patterns>;
>union : Symbol(union, Decl(contextualReturnRecursivePatternArguments.ts, 3, 94))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 4, 23))
>Patterns : Symbol(Patterns, Decl(contextualReturnRecursivePatternArguments.ts, 4, 29))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 4, 23))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 4, 23))
>patterns : Symbol(patterns, Decl(contextualReturnRecursivePatternArguments.ts, 4, 95))
>Patterns : Symbol(Patterns, Decl(contextualReturnRecursivePatternArguments.ts, 4, 29))
>Matcher : Symbol(Matcher, Decl(contextualReturnRecursivePatternArguments.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 4, 23))
>Patterns : Symbol(Patterns, Decl(contextualReturnRecursivePatternArguments.ts, 4, 29))
declare function optional<Input, Value extends unknown extends Input ? unknown : Pattern<Input>>(value: Value): Matcher<Input, Value>;
>optional : Symbol(optional, Decl(contextualReturnRecursivePatternArguments.ts, 4, 144))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 5, 26))
>Value : Symbol(Value, Decl(contextualReturnRecursivePatternArguments.ts, 5, 32))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 5, 26))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 5, 26))
>value : Symbol(value, Decl(contextualReturnRecursivePatternArguments.ts, 5, 97))
>Value : Symbol(Value, Decl(contextualReturnRecursivePatternArguments.ts, 5, 32))
>Matcher : Symbol(Matcher, Decl(contextualReturnRecursivePatternArguments.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 5, 26))
>Value : Symbol(Value, Decl(contextualReturnRecursivePatternArguments.ts, 5, 32))
declare function intersection<Input, Values extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...values: Values): Matcher<Input, Values>;
>intersection : Symbol(intersection, Decl(contextualReturnRecursivePatternArguments.ts, 5, 134))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 6, 30))
>Values : Symbol(Values, Decl(contextualReturnRecursivePatternArguments.ts, 6, 36))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 6, 30))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 6, 30))
>values : Symbol(values, Decl(contextualReturnRecursivePatternArguments.ts, 6, 100))
>Values : Symbol(Values, Decl(contextualReturnRecursivePatternArguments.ts, 6, 36))
>Matcher : Symbol(Matcher, Decl(contextualReturnRecursivePatternArguments.ts, 0, 0))
>Input : Symbol(Input, Decl(contextualReturnRecursivePatternArguments.ts, 6, 30))
>Values : Symbol(Values, Decl(contextualReturnRecursivePatternArguments.ts, 6, 36))
declare function accept<Value extends Pattern<{ type: "a" | "b" }>>(value: Value): void;
>accept : Symbol(accept, Decl(contextualReturnRecursivePatternArguments.ts, 6, 143))
>Value : Symbol(Value, Decl(contextualReturnRecursivePatternArguments.ts, 7, 24))
>Pattern : Symbol(Pattern, Decl(contextualReturnRecursivePatternArguments.ts, 2, 1))
>type : Symbol(type, Decl(contextualReturnRecursivePatternArguments.ts, 7, 47))
>value : Symbol(value, Decl(contextualReturnRecursivePatternArguments.ts, 7, 68))
>Value : Symbol(Value, Decl(contextualReturnRecursivePatternArguments.ts, 7, 24))
accept(optional({
>accept : Symbol(accept, Decl(contextualReturnRecursivePatternArguments.ts, 6, 143))
>optional : Symbol(optional, Decl(contextualReturnRecursivePatternArguments.ts, 4, 144))
// @ts-expect-error
type: union("oops"),
>type : Symbol(type, Decl(contextualReturnRecursivePatternArguments.ts, 9, 17))
>union : Symbol(union, Decl(contextualReturnRecursivePatternArguments.ts, 3, 94))
}));
accept(intersection({
>accept : Symbol(accept, Decl(contextualReturnRecursivePatternArguments.ts, 6, 143))
>intersection : Symbol(intersection, Decl(contextualReturnRecursivePatternArguments.ts, 5, 134))
// @ts-expect-error
type: union("oops"),
>type : Symbol(type, Decl(contextualReturnRecursivePatternArguments.ts, 13, 21))
>union : Symbol(union, Decl(contextualReturnRecursivePatternArguments.ts, 3, 94))
}));
@@ -0,0 +1,61 @@
//// [tests/cases/compiler/contextualReturnRecursivePatternArguments.ts] ////
=== contextualReturnRecursivePatternArguments.ts ===
interface Matcher<Input, Pattern = unknown> {
matcher(): { match(value: Input): boolean; pattern?: Pattern };
>matcher : () => { match(value: Input): boolean; pattern?: Pattern; }
>match : (value: Input) => boolean
>value : Input
>pattern : Pattern | undefined
}
type Pattern<Input> = Input | Matcher<Input> | { [Key in keyof Input]?: Pattern<Input[Key]> };
>Pattern : Pattern<Input>
declare function union<Input, Patterns extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...patterns: Patterns): Matcher<Input, Patterns>;
>union : <Input, Patterns extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...patterns: Patterns) => Matcher<Input, Patterns>
>patterns : Patterns
declare function optional<Input, Value extends unknown extends Input ? unknown : Pattern<Input>>(value: Value): Matcher<Input, Value>;
>optional : <Input, Value extends unknown extends Input ? unknown : Pattern<Input>>(value: Value) => Matcher<Input, Value>
>value : Value
declare function intersection<Input, Values extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...values: Values): Matcher<Input, Values>;
>intersection : <Input, Values extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...values: Values) => Matcher<Input, Values>
>values : Values
declare function accept<Value extends Pattern<{ type: "a" | "b" }>>(value: Value): void;
>accept : <Value extends Pattern<{ type: "a" | "b"; }>>(value: Value) => void
>type : "a" | "b"
>value : Value
accept(optional({
>accept(optional({ // @ts-expect-error type: union("oops"),})) : void
>accept : <Value extends Pattern<{ type: "a" | "b"; }>>(value: Value) => void
>optional({ // @ts-expect-error type: union("oops"),}) : Matcher<unknown, { type: Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>; }>
>optional : <Input, Value extends unknown extends Input ? unknown : Pattern<Input>>(value: Value) => Matcher<Input, Value>
>{ // @ts-expect-error type: union("oops"),} : { type: Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>; }
// @ts-expect-error
type: union("oops"),
>type : Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>
>union("oops") : Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>
>union : <Input, Patterns extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...patterns: Patterns) => Matcher<Input, Patterns>
>"oops" : "oops"
}));
accept(intersection({
>accept(intersection({ // @ts-expect-error type: union("oops"),})) : void
>accept : <Value extends Pattern<{ type: "a" | "b"; }>>(value: Value) => void
>intersection({ // @ts-expect-error type: union("oops"),}) : Matcher<unknown, [{ type: Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>; }]>
>intersection : <Input, Values extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...values: Values) => Matcher<Input, Values>
>{ // @ts-expect-error type: union("oops"),} : { type: Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>; }
// @ts-expect-error
type: union("oops"),
>type : Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>
>union("oops") : Matcher<"a" | "b", readonly [Pattern<"a" | "b">, ...Pattern<"a" | "b">[]]>
>union : <Input, Patterns extends readonly [Pattern<Input>, ...Pattern<Input>[]]>(...patterns: Patterns) => Matcher<Input, Patterns>
>"oops" : "oops"
}));
@@ -0,0 +1,47 @@
//// [tests/cases/compiler/contextualReturnSpreadPickInference.ts] ////
=== contextualReturnSpreadPickInference.ts ===
type Many<T> = T | readonly T[];
>Many : Symbol(Many, Decl(contextualReturnSpreadPickInference.ts, 0, 0))
>T : Symbol(T, Decl(contextualReturnSpreadPickInference.ts, 0, 10))
>T : Symbol(T, Decl(contextualReturnSpreadPickInference.ts, 0, 10))
>T : Symbol(T, Decl(contextualReturnSpreadPickInference.ts, 0, 10))
declare function pick<T extends object, Key extends keyof T>(
>pick : Symbol(pick, Decl(contextualReturnSpreadPickInference.ts, 0, 32))
>T : Symbol(T, Decl(contextualReturnSpreadPickInference.ts, 1, 22))
>Key : Symbol(Key, Decl(contextualReturnSpreadPickInference.ts, 1, 39))
>T : Symbol(T, Decl(contextualReturnSpreadPickInference.ts, 1, 22))
object: T,
>object : Symbol(object, Decl(contextualReturnSpreadPickInference.ts, 1, 61))
>T : Symbol(T, Decl(contextualReturnSpreadPickInference.ts, 1, 22))
...props: Many<Key>[]
>props : Symbol(props, Decl(contextualReturnSpreadPickInference.ts, 2, 14))
>Many : Symbol(Many, Decl(contextualReturnSpreadPickInference.ts, 0, 0))
>Key : Symbol(Key, Decl(contextualReturnSpreadPickInference.ts, 1, 39))
): Pick<T, Key>;
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(contextualReturnSpreadPickInference.ts, 1, 22))
>Key : Symbol(Key, Decl(contextualReturnSpreadPickInference.ts, 1, 39))
async function getPage(page: any): Promise<{ title: string; intro: string }> {
>getPage : Symbol(getPage, Decl(contextualReturnSpreadPickInference.ts, 4, 16))
>page : Symbol(page, Decl(contextualReturnSpreadPickInference.ts, 6, 23))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>title : Symbol(title, Decl(contextualReturnSpreadPickInference.ts, 6, 44))
>intro : Symbol(intro, Decl(contextualReturnSpreadPickInference.ts, 6, 59))
return {
title: "",
>title : Symbol(title, Decl(contextualReturnSpreadPickInference.ts, 7, 12))
...pick(page, ["intro"]),
>pick : Symbol(pick, Decl(contextualReturnSpreadPickInference.ts, 0, 32))
>page : Symbol(page, Decl(contextualReturnSpreadPickInference.ts, 6, 23))
};
}
@@ -0,0 +1,40 @@
//// [tests/cases/compiler/contextualReturnSpreadPickInference.ts] ////
=== contextualReturnSpreadPickInference.ts ===
type Many<T> = T | readonly T[];
>Many : Many<T>
declare function pick<T extends object, Key extends keyof T>(
>pick : <T extends object, Key extends keyof T>(object: T, ...props: Many<Key>[]) => Pick<T, Key>
object: T,
>object : T
...props: Many<Key>[]
>props : Many<Key>[]
): Pick<T, Key>;
async function getPage(page: any): Promise<{ title: string; intro: string }> {
>getPage : (page: any) => Promise<{ title: string; intro: string; }>
>page : any
>title : string
>intro : string
return {
>{ title: "", ...pick(page, ["intro"]), } : { title: string; intro: any; }
title: "",
>title : string
>"" : ""
...pick(page, ["intro"]),
>pick(page, ["intro"]) : Pick<any, "intro">
>pick : <T extends object, Key extends keyof T>(object: T, ...props: Many<Key>[]) => Pick<T, Key>
>page : any
>["intro"] : "intro"[]
>"intro" : "intro"
};
}
@@ -0,0 +1,42 @@
//// [tests/cases/compiler/contextualRuleMessageInference.ts] ////
=== contextualRuleMessageInference.ts ===
type DeferredInference<T> = [T][T extends unknown ? 0 : never];
>DeferredInference : Symbol(DeferredInference, Decl(contextualRuleMessageInference.ts, 0, 0))
>T : Symbol(T, Decl(contextualRuleMessageInference.ts, 0, 23))
>T : Symbol(T, Decl(contextualRuleMessageInference.ts, 0, 23))
>T : Symbol(T, Decl(contextualRuleMessageInference.ts, 0, 23))
declare function runRule<Message extends string>(
>runRule : Symbol(runRule, Decl(contextualRuleMessageInference.ts, 0, 63))
>Message : Symbol(Message, Decl(contextualRuleMessageInference.ts, 2, 25))
rule: Message,
>rule : Symbol(rule, Decl(contextualRuleMessageInference.ts, 2, 49))
>Message : Symbol(Message, Decl(contextualRuleMessageInference.ts, 2, 25))
tests: { invalid: readonly { errors: readonly { messageId: DeferredInference<Message> }[] }[] },
>tests : Symbol(tests, Decl(contextualRuleMessageInference.ts, 3, 18))
>invalid : Symbol(invalid, Decl(contextualRuleMessageInference.ts, 4, 12))
>errors : Symbol(errors, Decl(contextualRuleMessageInference.ts, 4, 32))
>messageId : Symbol(messageId, Decl(contextualRuleMessageInference.ts, 4, 51))
>DeferredInference : Symbol(DeferredInference, Decl(contextualRuleMessageInference.ts, 0, 0))
>Message : Symbol(Message, Decl(contextualRuleMessageInference.ts, 2, 25))
): void;
runRule("forbiddenAct", {
>runRule : Symbol(runRule, Decl(contextualRuleMessageInference.ts, 0, 63))
invalid: ["act()"].map(() => ({
>invalid : Symbol(invalid, Decl(contextualRuleMessageInference.ts, 7, 25))
>["act()"].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
errors: [{ messageId: "forbiddenAct" }],
>errors : Symbol(errors, Decl(contextualRuleMessageInference.ts, 8, 35))
>messageId : Symbol(messageId, Decl(contextualRuleMessageInference.ts, 9, 18))
})),
});
@@ -0,0 +1,47 @@
//// [tests/cases/compiler/contextualRuleMessageInference.ts] ////
=== contextualRuleMessageInference.ts ===
type DeferredInference<T> = [T][T extends unknown ? 0 : never];
>DeferredInference : DeferredInference<T>
declare function runRule<Message extends string>(
>runRule : <Message extends string>(rule: Message, tests: { invalid: readonly { errors: readonly { messageId: DeferredInference<Message>; }[]; }[]; }) => void
rule: Message,
>rule : Message
tests: { invalid: readonly { errors: readonly { messageId: DeferredInference<Message> }[] }[] },
>tests : { invalid: readonly { errors: readonly { messageId: DeferredInference<Message>; }[]; }[]; }
>invalid : readonly { errors: readonly { messageId: DeferredInference<Message>; }[]; }[]
>errors : readonly { messageId: DeferredInference<Message>; }[]
>messageId : DeferredInference<Message>
): void;
runRule("forbiddenAct", {
>runRule("forbiddenAct", { invalid: ["act()"].map(() => ({ errors: [{ messageId: "forbiddenAct" }], })),}) : void
>runRule : <Message extends string>(rule: Message, tests: { invalid: readonly { errors: readonly { messageId: DeferredInference<Message>; }[]; }[]; }) => void
>"forbiddenAct" : "forbiddenAct"
>{ invalid: ["act()"].map(() => ({ errors: [{ messageId: "forbiddenAct" }], })),} : { invalid: { errors: { messageId: "forbiddenAct"; }[]; }[]; }
invalid: ["act()"].map(() => ({
>invalid : { errors: { messageId: "forbiddenAct"; }[]; }[]
>["act()"].map(() => ({ errors: [{ messageId: "forbiddenAct" }], })) : { errors: { messageId: "forbiddenAct"; }[]; }[]
>["act()"].map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>["act()"] : string[]
>"act()" : "act()"
>map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>() => ({ errors: [{ messageId: "forbiddenAct" }], }) : () => { errors: { messageId: "forbiddenAct"; }[]; }
>({ errors: [{ messageId: "forbiddenAct" }], }) : { errors: { messageId: "forbiddenAct"; }[]; }
>{ errors: [{ messageId: "forbiddenAct" }], } : { errors: { messageId: "forbiddenAct"; }[]; }
errors: [{ messageId: "forbiddenAct" }],
>errors : { messageId: "forbiddenAct"; }[]
>[{ messageId: "forbiddenAct" }] : { messageId: "forbiddenAct"; }[]
>{ messageId: "forbiddenAct" } : { messageId: "forbiddenAct"; }
>messageId : "forbiddenAct"
>"forbiddenAct" : "forbiddenAct"
})),
});
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/correlatedLabelNullishFallback.ts] ////
//// [correlatedLabelNullishFallback.ts]
function label(options: { label: string; alias: string } | { label: object; alias?: string }) {
if (typeof options.label === "string") return options.alias ?? options.label;
}
//// [correlatedLabelNullishFallback.js]
"use strict";
function label(options) {
if (typeof options.label === "string")
return options.alias ?? options.label;
}
@@ -0,0 +1,23 @@
//// [tests/cases/compiler/correlatedLabelNullishFallback.ts] ////
=== correlatedLabelNullishFallback.ts ===
function label(options: { label: string; alias: string } | { label: object; alias?: string }) {
>label : Symbol(label, Decl(correlatedLabelNullishFallback.ts, 0, 0))
>options : Symbol(options, Decl(correlatedLabelNullishFallback.ts, 0, 15))
>label : Symbol(label, Decl(correlatedLabelNullishFallback.ts, 0, 25))
>alias : Symbol(alias, Decl(correlatedLabelNullishFallback.ts, 0, 40))
>label : Symbol(label, Decl(correlatedLabelNullishFallback.ts, 0, 60))
>alias : Symbol(alias, Decl(correlatedLabelNullishFallback.ts, 0, 75))
if (typeof options.label === "string") return options.alias ?? options.label;
>options.label : Symbol(label, Decl(correlatedLabelNullishFallback.ts, 0, 25), Decl(correlatedLabelNullishFallback.ts, 0, 60))
>options : Symbol(options, Decl(correlatedLabelNullishFallback.ts, 0, 15))
>label : Symbol(label, Decl(correlatedLabelNullishFallback.ts, 0, 25), Decl(correlatedLabelNullishFallback.ts, 0, 60))
>options.alias : Symbol(alias, Decl(correlatedLabelNullishFallback.ts, 0, 40), Decl(correlatedLabelNullishFallback.ts, 0, 75))
>options : Symbol(options, Decl(correlatedLabelNullishFallback.ts, 0, 15))
>alias : Symbol(alias, Decl(correlatedLabelNullishFallback.ts, 0, 40), Decl(correlatedLabelNullishFallback.ts, 0, 75))
>options.label : Symbol(label, Decl(correlatedLabelNullishFallback.ts, 0, 25), Decl(correlatedLabelNullishFallback.ts, 0, 60))
>options : Symbol(options, Decl(correlatedLabelNullishFallback.ts, 0, 15))
>label : Symbol(label, Decl(correlatedLabelNullishFallback.ts, 0, 25), Decl(correlatedLabelNullishFallback.ts, 0, 60))
}
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/correlatedLabelNullishFallback.ts] ////
=== correlatedLabelNullishFallback.ts ===
function label(options: { label: string; alias: string } | { label: object; alias?: string }) {
>label : (options: { label: string; alias: string; } | { label: object; alias?: string; }) => string | undefined
>options : { label: string; alias: string; } | { label: object; alias?: string; }
>label : string
>alias : string
>label : object
>alias : string | undefined
if (typeof options.label === "string") return options.alias ?? options.label;
>typeof options.label === "string" : boolean
>typeof options.label : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
>options.label : string | object
>options : { label: string; alias: string; } | { label: object; alias?: string; }
>label : string | object
>"string" : "string"
>options.alias ?? options.label : string
>options.alias : string | undefined
>options : { label: string; alias: string; } | { label: object; alias?: string; }
>alias : string | undefined
>options.label : string
>options : { label: string; alias: string; } | { label: object; alias?: string; }
>label : string
}
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/cssStyleDeclarationCompatibility.ts] ////
=== cssStyleDeclarationCompatibility.ts ===
declare const element: HTMLElement;
>element : Symbol(element, Decl(cssStyleDeclarationCompatibility.ts, 0, 13))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
const style: CSSStyleDeclaration = element.style;
>style : Symbol(style, Decl(cssStyleDeclarationCompatibility.ts, 1, 5))
>CSSStyleDeclaration : Symbol(CSSStyleDeclaration, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>element.style : Symbol(ElementCSSInlineStyle.style, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>element : Symbol(element, Decl(cssStyleDeclarationCompatibility.ts, 0, 13))
>style : Symbol(ElementCSSInlineStyle.style, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
[...element.style];
>element.style : Symbol(ElementCSSInlineStyle.style, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>element : Symbol(element, Decl(cssStyleDeclarationCompatibility.ts, 0, 13))
>style : Symbol(ElementCSSInlineStyle.style, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/cssStyleDeclarationCompatibility.ts] ////
=== cssStyleDeclarationCompatibility.ts ===
declare const element: HTMLElement;
>element : HTMLElement
const style: CSSStyleDeclaration = element.style;
>style : CSSStyleDeclaration
>element.style : CSSStyleDeclaration
>element : HTMLElement
>style : CSSStyleDeclaration
[...element.style];
>[...element.style] : string[]
>...element.style : string
>element.style : CSSStyleDeclaration
>element : HTMLElement
>style : CSSStyleDeclaration
@@ -0,0 +1,10 @@
//// [tests/cases/compiler/declarationDefaultImportSuggestion.ts] ////
=== store.d.ts ===
export interface Store {}
>Store : Symbol(Store, Decl(store.d.ts, 0, 0))
=== main.ts ===
import Store from "./store";
>Store : Symbol(Store, Decl(main.ts, 0, 6))
@@ -0,0 +1,10 @@
//// [tests/cases/compiler/declarationDefaultImportSuggestion.ts] ////
=== store.d.ts ===
export interface Store {}
=== main.ts ===
import Store from "./store";
>Store : typeof Store
@@ -0,0 +1,25 @@
error TS6059: File '/project/src/index.ts' is not under 'rootDir' '/project/example'. 'rootDir' is expected to contain all source files.
The file is in the program because:
Part of 'files' list in tsconfig.json
/project/example/tsconfig.json(3,9): error TS5011: The common source directory of 'tsconfig.json' is '../src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.
Visit https://aka.ms/ts6 for migration information.
!!! error TS6059: File '/project/src/index.ts' is not under 'rootDir' '/project/example'. 'rootDir' is expected to contain all source files.
!!! error TS6059: The file is in the program because:
!!! error TS6059: Part of 'files' list in tsconfig.json
!!! related TS1410 /project/example/tsconfig.json:5:15: File is matched by 'files' list specified here.
==== /project/example/tsconfig.json (1 errors) ====
{
"compilerOptions": {
"outDir": "."
~~~~~~~~
!!! error TS5011: The common source directory of 'tsconfig.json' is '../src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.
!!! error TS5011: Visit https://aka.ms/ts6 for migration information.
},
"files": ["../src/index.ts"]
}
==== /project/src/index.ts (0 errors) ====
export const value = 0;
@@ -0,0 +1,8 @@
//// [tests/cases/compiler/defaultRootDirExternalFiles.ts] ////
//// [index.ts]
export const value = 0;
//// [index.js]
export const value = 0;
@@ -0,0 +1,6 @@
//// [tests/cases/compiler/defaultRootDirExternalFiles.ts] ////
=== /project/src/index.ts ===
export const value = 0;
>value : Symbol(value, Decl(index.ts, 0, 12))
@@ -0,0 +1,7 @@
//// [tests/cases/compiler/defaultRootDirExternalFiles.ts] ////
=== /project/src/index.ts ===
export const value = 0;
>value : 0
>0 : 0
@@ -0,0 +1,28 @@
error TS5011: The common source directory of 'tsconfig.json' is '../src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.
Visit https://aka.ms/ts6 for migration information.
error TS6059: File '/project/src/index.ts' is not under 'rootDir' '/project/example'. 'rootDir' is expected to contain all source files.
The file is in the program because:
Matched by include pattern '../src' in '/project/example/tsconfig.json'
!!! error TS5011: The common source directory of 'tsconfig.json' is '../src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.
!!! error TS5011: Visit https://aka.ms/ts6 for migration information.
!!! error TS6059: File '/project/src/index.ts' is not under 'rootDir' '/project/example'. 'rootDir' is expected to contain all source files.
!!! error TS6059: The file is in the program because:
!!! error TS6059: Matched by include pattern '../src' in '/project/example/tsconfig.json'
==== /project/example/tsconfig.json (0 errors) ====
{
"extends": "../tsconfig.json"
}
==== /project/src/index.ts (0 errors) ====
export const value = 0;
==== /project/tsconfig.json (0 errors) ====
{
"compilerOptions": {
"outDir": "lib"
},
"include": ["src"]
}
@@ -0,0 +1,16 @@
//// [tests/cases/compiler/defaultRootDirInheritedInclude.ts] ////
//// [tsconfig.json]
{
"compilerOptions": {
"outDir": "lib"
},
"include": ["src"]
}
//// [index.ts]
export const value = 0;
//// [index.js]
export const value = 0;
@@ -0,0 +1,6 @@
//// [tests/cases/compiler/defaultRootDirInheritedInclude.ts] ////
=== /project/src/index.ts ===
export const value = 0;
>value : Symbol(value, Decl(index.ts, 0, 12))
@@ -0,0 +1,7 @@
//// [tests/cases/compiler/defaultRootDirInheritedInclude.ts] ////
=== /project/src/index.ts ===
export const value = 0;
>value : 0
>0 : 0
@@ -0,0 +1,18 @@
/main.mts(1,23): error TS2307: Cannot find module 'engine' or its corresponding type declarations.
/main.mts(2,35): error TS2307: Cannot find module 'engine' or its corresponding type declarations.
==== /main.mts (2 errors) ====
import { value } from "engine";
~~~~~~~~
!!! error TS2307: Cannot find module 'engine' or its corresponding type declarations.
export { default as engine } from "engine";
~~~~~~~~
!!! error TS2307: Cannot find module 'engine' or its corresponding type declarations.
==== /node_modules/@types/runtime/index.d.ts (0 errors) ====
declare module "engine" {
export const value: number;
export default function read(): void;
}
@@ -0,0 +1,9 @@
//// [tests/cases/compiler/defaultTypesExcludeAmbientModuleImports.ts] ////
=== /main.mts ===
import { value } from "engine";
>value : Symbol(value, Decl(main.mts, 0, 8))
export { default as engine } from "engine";
>engine : Symbol(engine, Decl(main.mts, 1, 8))
@@ -0,0 +1,10 @@
//// [tests/cases/compiler/defaultTypesExcludeAmbientModuleImports.ts] ////
=== /main.mts ===
import { value } from "engine";
>value : any
export { default as engine } from "engine";
>default : any
>engine : any
@@ -0,0 +1,11 @@
/main.ts(1,1): error TS2304: Cannot find name '__dirname'.
==== /main.ts (1 errors) ====
__dirname;
~~~~~~~~~
!!! error TS2304: Cannot find name '__dirname'.
==== /node_modules/@types/runtime/index.d.ts (0 errors) ====
declare const __dirname: string;
@@ -0,0 +1,6 @@
//// [tests/cases/compiler/defaultTypesExcludeAmbientPackages.ts] ////
=== /main.ts ===
__dirname;
@@ -0,0 +1,6 @@
//// [tests/cases/compiler/defaultTypesExcludeAmbientPackages.ts] ////
=== /main.ts ===
__dirname;
>__dirname : any
@@ -0,0 +1,20 @@
error TS2318: Cannot find global type 'Boolean'.
error TS2318: Cannot find global type 'CallableFunction'.
error TS2318: Cannot find global type 'IArguments'.
error TS2318: Cannot find global type 'NewableFunction'.
error TS2318: Cannot find global type 'Number'.
error TS2318: Cannot find global type 'Object'.
!!! error TS2318: Cannot find global type 'Boolean'.
!!! error TS2318: Cannot find global type 'CallableFunction'.
!!! error TS2318: Cannot find global type 'IArguments'.
!!! error TS2318: Cannot find global type 'NewableFunction'.
!!! error TS2318: Cannot find global type 'Number'.
!!! error TS2318: Cannot find global type 'Object'.
==== /main.ts (0 errors) ====
export {};
==== /node_modules/@types/runtime/index.d.ts (0 errors) ====
/// <reference lib="es2020" />
@@ -0,0 +1,6 @@
//// [tests/cases/compiler/defaultTypesExcludeBaseLibraryReferences.ts] ////
=== /main.ts ===
export {};
@@ -0,0 +1,6 @@
//// [tests/cases/compiler/defaultTypesExcludeBaseLibraryReferences.ts] ////
=== /main.ts ===
export {};
@@ -0,0 +1,11 @@
/main.ts(1,18): error TS2550: Property 'includes' does not exist on type 'string[]'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2016' or later.
==== /main.ts (1 errors) ====
["workflow.yml"].includes("workflow.yml");
~~~~~~~~
!!! error TS2550: Property 'includes' does not exist on type 'string[]'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2016' or later.
==== /node_modules/@types/runtime/index.d.ts (0 errors) ====
/// <reference lib="es2018" />
@@ -0,0 +1,6 @@
//// [tests/cases/compiler/defaultTypesExcludeLibraryReferences.ts] ////
=== /main.ts ===
["workflow.yml"].includes("workflow.yml");
@@ -0,0 +1,11 @@
//// [tests/cases/compiler/defaultTypesExcludeLibraryReferences.ts] ////
=== /main.ts ===
["workflow.yml"].includes("workflow.yml");
>["workflow.yml"].includes("workflow.yml") : any
>["workflow.yml"].includes : any
>["workflow.yml"] : string[]
>"workflow.yml" : "workflow.yml"
>includes : any
>"workflow.yml" : "workflow.yml"
@@ -0,0 +1,11 @@
//// [tests/cases/compiler/defaultWeakMapInferredPropertyAssignment.ts] ////
//// [defaultWeakMapInferredPropertyAssignment.ts]
const frameInfo = { frames: new WeakMap() };
const target: { frames: WeakMap<{ id: string }, number> } = frameInfo;
//// [defaultWeakMapInferredPropertyAssignment.js]
"use strict";
const frameInfo = { frames: new WeakMap() };
const target = frameInfo;
@@ -0,0 +1,15 @@
//// [tests/cases/compiler/defaultWeakMapInferredPropertyAssignment.ts] ////
=== defaultWeakMapInferredPropertyAssignment.ts ===
const frameInfo = { frames: new WeakMap() };
>frameInfo : Symbol(frameInfo, Decl(defaultWeakMapInferredPropertyAssignment.ts, 0, 5))
>frames : Symbol(frames, Decl(defaultWeakMapInferredPropertyAssignment.ts, 0, 19))
>WeakMap : Symbol(WeakMap, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
const target: { frames: WeakMap<{ id: string }, number> } = frameInfo;
>target : Symbol(target, Decl(defaultWeakMapInferredPropertyAssignment.ts, 1, 5))
>frames : Symbol(frames, Decl(defaultWeakMapInferredPropertyAssignment.ts, 1, 15))
>WeakMap : Symbol(WeakMap, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>id : Symbol(id, Decl(defaultWeakMapInferredPropertyAssignment.ts, 1, 33))
>frameInfo : Symbol(frameInfo, Decl(defaultWeakMapInferredPropertyAssignment.ts, 0, 5))
@@ -0,0 +1,16 @@
//// [tests/cases/compiler/defaultWeakMapInferredPropertyAssignment.ts] ////
=== defaultWeakMapInferredPropertyAssignment.ts ===
const frameInfo = { frames: new WeakMap() };
>frameInfo : { frames: WeakMap<WeakKey, any>; }
>{ frames: new WeakMap() } : { frames: WeakMap<WeakKey, any>; }
>frames : WeakMap<WeakKey, any>
>new WeakMap() : WeakMap<WeakKey, any>
>WeakMap : WeakMapConstructor
const target: { frames: WeakMap<{ id: string }, number> } = frameInfo;
>target : { frames: WeakMap<{ id: string; }, number>; }
>frames : WeakMap<{ id: string; }, number>
>id : string
>frameInfo : { frames: WeakMap<WeakKey, any>; }
@@ -0,0 +1,17 @@
distributedRecursiveMappedType.ts(2,49): error TS2344: Type 'Input[Key]' does not satisfy the constraint 'Shape[Key]'.
Type 'Input' is not assignable to type 'Shape'.
'Input' is only assignable to the non-distributed 'Shape', but 'Shape' has been distributed here.
distributedRecursiveMappedType.ts(2,49): error TS2536: Type 'Key' cannot be used to index type 'Input'.
==== distributedRecursiveMappedType.ts (2 errors) ====
type Exact<Shape, Input extends Shape> = Shape extends Shape
? { [Key in keyof Shape]: Exact<Shape[Key], Input[Key]> }
~~~~~~~~~~
!!! error TS2344: Type 'Input[Key]' does not satisfy the constraint 'Shape[Key]'.
!!! error TS2344: Type 'Input' is not assignable to type 'Shape'.
!!! error TS2344: 'Input' is only assignable to the non-distributed 'Shape', but 'Shape' has been distributed here.
~~~~~~~~~~
!!! error TS2536: Type 'Key' cannot be used to index type 'Input'.
: never;
@@ -0,0 +1,22 @@
//// [tests/cases/compiler/distributedRecursiveMappedType.ts] ////
=== distributedRecursiveMappedType.ts ===
type Exact<Shape, Input extends Shape> = Shape extends Shape
>Exact : Symbol(Exact, Decl(distributedRecursiveMappedType.ts, 0, 0))
>Shape : Symbol(Shape, Decl(distributedRecursiveMappedType.ts, 0, 11))
>Input : Symbol(Input, Decl(distributedRecursiveMappedType.ts, 0, 17))
>Shape : Symbol(Shape, Decl(distributedRecursiveMappedType.ts, 0, 11))
>Shape : Symbol(Shape, Decl(distributedRecursiveMappedType.ts, 0, 11))
>Shape : Symbol(Shape, Decl(distributedRecursiveMappedType.ts, 0, 11))
? { [Key in keyof Shape]: Exact<Shape[Key], Input[Key]> }
>Key : Symbol(Key, Decl(distributedRecursiveMappedType.ts, 1, 9))
>Shape : Symbol(Shape, Decl(distributedRecursiveMappedType.ts, 0, 11))
>Exact : Symbol(Exact, Decl(distributedRecursiveMappedType.ts, 0, 0))
>Shape : Symbol(Shape, Decl(distributedRecursiveMappedType.ts, 0, 11))
>Key : Symbol(Key, Decl(distributedRecursiveMappedType.ts, 1, 9))
>Input : Symbol(Input, Decl(distributedRecursiveMappedType.ts, 0, 17))
>Key : Symbol(Key, Decl(distributedRecursiveMappedType.ts, 1, 9))
: never;
Loaded 100 of 479 files, more files were not shown because too many files have changed in this diff. Show more