diff --git a/.github/workflows/accept-baselines-fix-lints.yaml b/.github/workflows/accept-baselines-fix-lints.yaml index 7130e01a75a88..5cce3fd378cff 100644 --- a/.github/workflows/accept-baselines-fix-lints.yaml +++ b/.github/workflows/accept-baselines-fix-lints.yaml @@ -21,6 +21,8 @@ jobs: with: token: ${{ secrets.TS_BOT_GITHUB_TOKEN }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 'lts/*' - name: Configure Git, Run Tests, Update Baselines, Apply Fixes run: | diff --git a/.github/workflows/new-release-branch.yaml b/.github/workflows/new-release-branch.yaml index 23efbe1a8bf5b..5b9fe42816b59 100644 --- a/.github/workflows/new-release-branch.yaml +++ b/.github/workflows/new-release-branch.yaml @@ -24,6 +24,8 @@ jobs: fetch-depth: 0 # Default is 1; need to set to 0 to get the benefits of blob:none. token: ${{ secrets.TS_BOT_GITHUB_TOKEN }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 'lts/*' - run: | npm --version # corepack enable npm diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 9aa7910403fc3..fb08905dc2faf 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -26,6 +26,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: + node-version: 'lts/*' # Use NODE_AUTH_TOKEN environment variable to authenticate to this registry. registry-url: https://registry.npmjs.org/ - run: | diff --git a/.github/workflows/release-branch-artifact.yaml b/.github/workflows/release-branch-artifact.yaml index 99862ff6066a2..af238ceeabb3a 100644 --- a/.github/workflows/release-branch-artifact.yaml +++ b/.github/workflows/release-branch-artifact.yaml @@ -21,6 +21,8 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 'lts/*' - run: | npm --version # corepack enable npm diff --git a/.github/workflows/rich-navigation.yml b/.github/workflows/rich-navigation.yml index 798658d44a343..d0bc7146826f2 100644 --- a/.github/workflows/rich-navigation.yml +++ b/.github/workflows/rich-navigation.yml @@ -27,6 +27,8 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 'lts/*' - name: Install dependencies run: npm ci diff --git a/.github/workflows/set-version.yaml b/.github/workflows/set-version.yaml index 43cf921ad312a..6ca38dcd3cfe6 100644 --- a/.github/workflows/set-version.yaml +++ b/.github/workflows/set-version.yaml @@ -22,6 +22,8 @@ jobs: ref: ${{ github.event.client_payload.branch_name }} token: ${{ secrets.TS_BOT_GITHUB_TOKEN }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 'lts/*' - run: | npm --version # corepack enable npm diff --git a/.github/workflows/sync-branch.yaml b/.github/workflows/sync-branch.yaml index b754e945a78b5..5a4efac9a79fc 100644 --- a/.github/workflows/sync-branch.yaml +++ b/.github/workflows/sync-branch.yaml @@ -24,6 +24,8 @@ jobs: steps: - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 'lts/*' - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ github.event.inputs.branch_name || github.event.client_payload.branch_name }} diff --git a/.github/workflows/twoslash-repros.yaml b/.github/workflows/twoslash-repros.yaml index 5f389f70bbea2..33c0f83a8e146 100644 --- a/.github/workflows/twoslash-repros.yaml +++ b/.github/workflows/twoslash-repros.yaml @@ -41,6 +41,8 @@ jobs: - if: ${{ !github.event.inputs.bisect }} uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 'lts/*' - uses: microsoft/TypeScript-Twoslash-Repro-Action@8680b5b290d48a7badbc7ba65971d526c61b86b8 # master with: github-token: ${{ secrets.TS_BOT_GITHUB_TOKEN }} diff --git a/lib/tsc.js b/lib/tsc.js index eb9b776f9c9d8..f4e4fed2bc00f 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -18,7 +18,7 @@ and limitations under the License. // src/compiler/corePublic.ts var versionMajorMinor = "5.4"; -var version = "5.4.4"; +var version = "5.4.5"; // src/compiler/core.ts var emptyArray = []; @@ -55344,12 +55344,10 @@ function createTypeChecker(host) { const target = type.target ?? type; const typeVariable = getHomomorphicTypeVariable(target); if (typeVariable && !target.declaration.nameType) { - const constraint = getConstraintTypeFromMappedType(type); - if (constraint.flags & 4194304 /* Index */) { - const baseConstraint = getBaseConstraintOfType(constraint.type); - if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { - return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); - } + const modifiersType = getModifiersTypeFromMappedType(type); + const baseConstraint = isGenericMappedType(modifiersType) ? getApparentTypeOfMappedType(modifiersType) : getBaseConstraintOfType(modifiersType); + if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { + return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } return type; @@ -55510,13 +55508,13 @@ function createTypeChecker(host) { } function getUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment) { var _a, _b, _c; - let property = ((_a = type.propertyCacheWithoutObjectFunctionPropertyAugment) == null ? void 0 : _a.get(name)) || !skipObjectFunctionPropertyAugment ? (_b = type.propertyCache) == null ? void 0 : _b.get(name) : void 0; + let property = skipObjectFunctionPropertyAugment ? (_a = type.propertyCacheWithoutObjectFunctionPropertyAugment) == null ? void 0 : _a.get(name) : (_b = type.propertyCache) == null ? void 0 : _b.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); if (property) { const properties = skipObjectFunctionPropertyAugment ? type.propertyCacheWithoutObjectFunctionPropertyAugment || (type.propertyCacheWithoutObjectFunctionPropertyAugment = createSymbolTable()) : type.propertyCache || (type.propertyCache = createSymbolTable()); properties.set(name, property); - if (skipObjectFunctionPropertyAugment && !((_c = type.propertyCache) == null ? void 0 : _c.get(name))) { + if (skipObjectFunctionPropertyAugment && !(getCheckFlags(property) & 48 /* Partial */) && !((_c = type.propertyCache) == null ? void 0 : _c.get(name))) { const properties2 = type.propertyCache || (type.propertyCache = createSymbolTable()); properties2.set(name, property); } diff --git a/lib/tsserver.js b/lib/tsserver.js index 6a1c0318396c8..3f1ce62663e3c 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -2340,7 +2340,7 @@ module.exports = __toCommonJS(server_exports); // src/compiler/corePublic.ts var versionMajorMinor = "5.4"; -var version = "5.4.4"; +var version = "5.4.5"; var Comparison = /* @__PURE__ */ ((Comparison3) => { Comparison3[Comparison3["LessThan"] = -1] = "LessThan"; Comparison3[Comparison3["EqualTo"] = 0] = "EqualTo"; @@ -60088,12 +60088,10 @@ function createTypeChecker(host) { const target = type.target ?? type; const typeVariable = getHomomorphicTypeVariable(target); if (typeVariable && !target.declaration.nameType) { - const constraint = getConstraintTypeFromMappedType(type); - if (constraint.flags & 4194304 /* Index */) { - const baseConstraint = getBaseConstraintOfType(constraint.type); - if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { - return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); - } + const modifiersType = getModifiersTypeFromMappedType(type); + const baseConstraint = isGenericMappedType(modifiersType) ? getApparentTypeOfMappedType(modifiersType) : getBaseConstraintOfType(modifiersType); + if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { + return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } return type; @@ -60254,13 +60252,13 @@ function createTypeChecker(host) { } function getUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment) { var _a, _b, _c; - let property = ((_a = type.propertyCacheWithoutObjectFunctionPropertyAugment) == null ? void 0 : _a.get(name)) || !skipObjectFunctionPropertyAugment ? (_b = type.propertyCache) == null ? void 0 : _b.get(name) : void 0; + let property = skipObjectFunctionPropertyAugment ? (_a = type.propertyCacheWithoutObjectFunctionPropertyAugment) == null ? void 0 : _a.get(name) : (_b = type.propertyCache) == null ? void 0 : _b.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); if (property) { const properties = skipObjectFunctionPropertyAugment ? type.propertyCacheWithoutObjectFunctionPropertyAugment || (type.propertyCacheWithoutObjectFunctionPropertyAugment = createSymbolTable()) : type.propertyCache || (type.propertyCache = createSymbolTable()); properties.set(name, property); - if (skipObjectFunctionPropertyAugment && !((_c = type.propertyCache) == null ? void 0 : _c.get(name))) { + if (skipObjectFunctionPropertyAugment && !(getCheckFlags(property) & 48 /* Partial */) && !((_c = type.propertyCache) == null ? void 0 : _c.get(name))) { const properties2 = type.propertyCache || (type.propertyCache = createSymbolTable()); properties2.set(name, property); } @@ -160459,7 +160457,8 @@ function getCompletionEntriesFromSymbols(symbols, entries, replacementToken, con } function symbolAppearsToBeTypeOnly(symbol) { var _a; - return !(symbol.flags & 111551 /* Value */) && (!isInJSFile((_a = symbol.declarations) == null ? void 0 : _a[0]) || !!(symbol.flags & 788968 /* Type */)); + const flags = getCombinedLocalAndExportSymbolFlags(skipAlias(symbol, typeChecker)); + return !(flags & 111551 /* Value */) && (!isInJSFile((_a = symbol.declarations) == null ? void 0 : _a[0]) || !!(flags & 788968 /* Type */)); } } function getLabelCompletionAtPosition(node) { diff --git a/lib/typescript.js b/lib/typescript.js index 018350e49dbc2..22053b17844ef 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -35,7 +35,7 @@ var ts = (() => { "src/compiler/corePublic.ts"() { "use strict"; versionMajorMinor = "5.4"; - version = "5.4.4"; + version = "5.4.5"; Comparison = /* @__PURE__ */ ((Comparison3) => { Comparison3[Comparison3["LessThan"] = -1] = "LessThan"; Comparison3[Comparison3["EqualTo"] = 0] = "EqualTo"; @@ -57843,12 +57843,10 @@ ${lanes.join("\n")} const target = type.target ?? type; const typeVariable = getHomomorphicTypeVariable(target); if (typeVariable && !target.declaration.nameType) { - const constraint = getConstraintTypeFromMappedType(type); - if (constraint.flags & 4194304 /* Index */) { - const baseConstraint = getBaseConstraintOfType(constraint.type); - if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { - return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); - } + const modifiersType = getModifiersTypeFromMappedType(type); + const baseConstraint = isGenericMappedType(modifiersType) ? getApparentTypeOfMappedType(modifiersType) : getBaseConstraintOfType(modifiersType); + if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { + return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } return type; @@ -58009,13 +58007,13 @@ ${lanes.join("\n")} } function getUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment) { var _a, _b, _c; - let property = ((_a = type.propertyCacheWithoutObjectFunctionPropertyAugment) == null ? void 0 : _a.get(name)) || !skipObjectFunctionPropertyAugment ? (_b = type.propertyCache) == null ? void 0 : _b.get(name) : void 0; + let property = skipObjectFunctionPropertyAugment ? (_a = type.propertyCacheWithoutObjectFunctionPropertyAugment) == null ? void 0 : _a.get(name) : (_b = type.propertyCache) == null ? void 0 : _b.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); if (property) { const properties = skipObjectFunctionPropertyAugment ? type.propertyCacheWithoutObjectFunctionPropertyAugment || (type.propertyCacheWithoutObjectFunctionPropertyAugment = createSymbolTable()) : type.propertyCache || (type.propertyCache = createSymbolTable()); properties.set(name, property); - if (skipObjectFunctionPropertyAugment && !((_c = type.propertyCache) == null ? void 0 : _c.get(name))) { + if (skipObjectFunctionPropertyAugment && !(getCheckFlags(property) & 48 /* Partial */) && !((_c = type.propertyCache) == null ? void 0 : _c.get(name))) { const properties2 = type.propertyCache || (type.propertyCache = createSymbolTable()); properties2.set(name, property); } @@ -159682,7 +159680,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")} } function symbolAppearsToBeTypeOnly(symbol) { var _a; - return !(symbol.flags & 111551 /* Value */) && (!isInJSFile((_a = symbol.declarations) == null ? void 0 : _a[0]) || !!(symbol.flags & 788968 /* Type */)); + const flags = getCombinedLocalAndExportSymbolFlags(skipAlias(symbol, typeChecker)); + return !(flags & 111551 /* Value */) && (!isInJSFile((_a = symbol.declarations) == null ? void 0 : _a[0]) || !!(flags & 788968 /* Type */)); } } function getLabelCompletionAtPosition(node) { diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 9c8eb8b080270..e84a729bbc1b0 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -54,7 +54,7 @@ var path = __toESM(require("path")); // src/compiler/corePublic.ts var versionMajorMinor = "5.4"; -var version = "5.4.4"; +var version = "5.4.5"; // src/compiler/core.ts var emptyArray = []; diff --git a/package-lock.json b/package-lock.json index 81ae0832de0a4..79a30fd716021 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typescript", - "version": "5.4.4", + "version": "5.4.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typescript", - "version": "5.4.4", + "version": "5.4.5", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 96a0b9aefca81..f25964993ac18 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "5.4.4", + "version": "5.4.5", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 175caa9eef16e..b2f5047e9d3ce 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14552,16 +14552,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type.resolvedApparentType || (type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type)); } - function getResolvedApparentTypeOfMappedType(type: MappedType) { + function getResolvedApparentTypeOfMappedType(type: MappedType): Type { const target = (type.target ?? type) as MappedType; const typeVariable = getHomomorphicTypeVariable(target); if (typeVariable && !target.declaration.nameType) { - const constraint = getConstraintTypeFromMappedType(type); - if (constraint.flags & TypeFlags.Index) { - const baseConstraint = getBaseConstraintOfType((constraint as IndexType).type); - if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { - return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); - } + // We have a homomorphic mapped type or an instantiation of a homomorphic mapped type, i.e. a type + // of the form { [P in keyof T]: X }. Obtain the modifiers type (the T of the keyof T), and if it is + // another generic mapped type, recursively obtain its apparent type. Otherwise, obtain its base + // constraint. Then, if every constituent of the base constraint is an array or tuple type, apply + // this mapped type to the base constraint. It is safe to recurse when the modifiers type is a + // mapped type because we protect again circular constraints in getTypeFromMappedTypeNode. + const modifiersType = getModifiersTypeFromMappedType(type); + const baseConstraint = isGenericMappedType(modifiersType) ? getApparentTypeOfMappedType(modifiersType) : getBaseConstraintOfType(modifiersType); + if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { + return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } return type; @@ -14788,8 +14792,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { - let property = type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) || - !skipObjectFunctionPropertyAugment ? type.propertyCache?.get(name) : undefined; + let property = skipObjectFunctionPropertyAugment ? + type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) : + type.propertyCache?.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); if (property) { @@ -14797,7 +14802,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() : type.propertyCache ||= createSymbolTable(); properties.set(name, property); - if (skipObjectFunctionPropertyAugment && !type.propertyCache?.get(name)) { + // Propagate an entry from the non-augmented cache to the augmented cache unless the property is partial. + if (skipObjectFunctionPropertyAugment && !(getCheckFlags(property) & CheckFlags.Partial) && !type.propertyCache?.get(name)) { const properties = type.propertyCache ||= createSymbolTable(); properties.set(name, property); } diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index cea0a82974f1c..cf534f3db3af5 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -4,7 +4,7 @@ export const versionMajorMinor = "5.4"; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types -export const version = "5.4.4" as string; +export const version = "5.4.5" as string; /** * Type of objects whose values are all of the same type. diff --git a/src/services/completions.ts b/src/services/completions.ts index f41a00c716c8b..a074492cad678 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2674,7 +2674,8 @@ export function getCompletionEntriesFromSymbols( } function symbolAppearsToBeTypeOnly(symbol: Symbol): boolean { - return !(symbol.flags & SymbolFlags.Value) && (!isInJSFile(symbol.declarations?.[0]) || !!(symbol.flags & SymbolFlags.Type)); + const flags = getCombinedLocalAndExportSymbolFlags(skipAlias(symbol, typeChecker)); + return !(flags & SymbolFlags.Value) && (!isInJSFile(symbol.declarations?.[0]) || !!(flags & SymbolFlags.Type)); } } diff --git a/tests/baselines/reference/homomorphicMappedTypeNesting.symbols b/tests/baselines/reference/homomorphicMappedTypeNesting.symbols new file mode 100644 index 0000000000000..da939c18d6efb --- /dev/null +++ b/tests/baselines/reference/homomorphicMappedTypeNesting.symbols @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/homomorphicMappedTypeNesting.ts] //// + +=== homomorphicMappedTypeNesting.ts === +// Repro from #58060 + +type Box = { v: T }; +>Box : Symbol(Box, Decl(homomorphicMappedTypeNesting.ts, 0, 0)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 2, 9)) +>v : Symbol(v, Decl(homomorphicMappedTypeNesting.ts, 2, 30)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 2, 9)) + +type Test = T +>Test : Symbol(Test, Decl(homomorphicMappedTypeNesting.ts, 2, 38)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 4, 10)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 4, 10)) + +type UnboxArray = { +>UnboxArray : Symbol(UnboxArray, Decl(homomorphicMappedTypeNesting.ts, 4, 33)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 6, 16)) + + [K in keyof T]: T[K] extends Box ? R : never; +>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 7, 5)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 6, 16)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 6, 16)) +>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 7, 5)) +>Box : Symbol(Box, Decl(homomorphicMappedTypeNesting.ts, 0, 0)) +>R : Symbol(R, Decl(homomorphicMappedTypeNesting.ts, 7, 42)) +>R : Symbol(R, Decl(homomorphicMappedTypeNesting.ts, 7, 42)) + +}; + +type Identity = { [K in keyof T]: T[K] }; +>Identity : Symbol(Identity, Decl(homomorphicMappedTypeNesting.ts, 8, 2)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 10, 14)) +>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 10, 22)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 10, 14)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 10, 14)) +>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 10, 22)) + +declare function fnBad>>(...args: T): Test>>; +>fnBad : Symbol(fnBad, Decl(homomorphicMappedTypeNesting.ts, 10, 44)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 12, 23)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Box : Symbol(Box, Decl(homomorphicMappedTypeNesting.ts, 0, 0)) +>args : Symbol(args, Decl(homomorphicMappedTypeNesting.ts, 12, 53)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 12, 23)) +>Test : Symbol(Test, Decl(homomorphicMappedTypeNesting.ts, 2, 38)) +>Identity : Symbol(Identity, Decl(homomorphicMappedTypeNesting.ts, 8, 2)) +>UnboxArray : Symbol(UnboxArray, Decl(homomorphicMappedTypeNesting.ts, 4, 33)) +>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 12, 23)) + diff --git a/tests/baselines/reference/homomorphicMappedTypeNesting.types b/tests/baselines/reference/homomorphicMappedTypeNesting.types new file mode 100644 index 0000000000000..82eb61f12bc6e --- /dev/null +++ b/tests/baselines/reference/homomorphicMappedTypeNesting.types @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/homomorphicMappedTypeNesting.ts] //// + +=== homomorphicMappedTypeNesting.ts === +// Repro from #58060 + +type Box = { v: T }; +>Box : Box +>v : T + +type Test = T +>Test : T + +type UnboxArray = { +>UnboxArray : UnboxArray + + [K in keyof T]: T[K] extends Box ? R : never; +}; + +type Identity = { [K in keyof T]: T[K] }; +>Identity : Identity + +declare function fnBad>>(...args: T): Test>>; +>fnBad : []>(...args: T) => Test>> +>args : T + diff --git a/tests/cases/compiler/homomorphicMappedTypeNesting.ts b/tests/cases/compiler/homomorphicMappedTypeNesting.ts new file mode 100644 index 0000000000000..630c4d40cf51d --- /dev/null +++ b/tests/cases/compiler/homomorphicMappedTypeNesting.ts @@ -0,0 +1,16 @@ +// @strict: true +// @noEmit: true + +// Repro from #58060 + +type Box = { v: T }; + +type Test = T + +type UnboxArray = { + [K in keyof T]: T[K] extends Box ? R : never; +}; + +type Identity = { [K in keyof T]: T[K] }; + +declare function fnBad>>(...args: T): Test>>; diff --git a/tests/cases/fourslash/jsFileImportNoTypes2.ts b/tests/cases/fourslash/jsFileImportNoTypes2.ts new file mode 100644 index 0000000000000..548cf0bd3332a --- /dev/null +++ b/tests/cases/fourslash/jsFileImportNoTypes2.ts @@ -0,0 +1,59 @@ +/// + +// @allowJs: true + +// @Filename: /default.ts +//// export default class TestDefaultClass {} + +// @Filename: /defaultType.ts +//// export default interface TestDefaultInterface {} + +// @Filename: /reExport/toReExport.ts +//// export class TestClassReExport {} +//// export interface TestInterfaceReExport {} + +// @Filename: /reExport/index.ts +//// export { TestClassReExport, TestInterfaceReExport } from './toReExport'; + +// @Filename: /exportList.ts +//// class TestClassExportList {}; +//// interface TestInterfaceExportList {}; +//// export { TestClassExportList, TestInterfaceExportList }; + +// @Filename: /baseline.ts +//// export class TestClassBaseline {} +//// export interface TestInterfaceBaseline {} + +// @Filename: /a.js +//// import /**/ + +verify.completions({ + marker: "", + isNewIdentifierLocation: true, + exact: [ + { + name: "TestClassBaseline", + insertText: "import { TestClassBaseline } from \"./baseline\";", + source: "./baseline", + }, + { + name: "TestClassExportList", + insertText: "import { TestClassExportList } from \"./exportList\";", + source: "./exportList", + }, + { + name: "TestClassReExport", + insertText: "import { TestClassReExport } from \"./reExport\";", + source: "./reExport", + }, + { + name: "TestDefaultClass", + insertText: "import TestDefaultClass from \"./default\";", + source: "./default", + }, + ], + preferences: { + includeCompletionsForImportStatements: true, + includeCompletionsWithInsertText: true, + } +}); diff --git a/tests/cases/fourslash/partialUnionPropertyCacheInconsistentErrors.ts b/tests/cases/fourslash/partialUnionPropertyCacheInconsistentErrors.ts new file mode 100644 index 0000000000000..7d793b520fa05 --- /dev/null +++ b/tests/cases/fourslash/partialUnionPropertyCacheInconsistentErrors.ts @@ -0,0 +1,45 @@ +/// + +// @strict: true +// @lib: esnext + +//// interface ComponentOptions { +//// setup?: (props: Props) => void; +//// name?: string; +//// } +//// +//// interface FunctionalComponent

{ +//// (props: P): void; +//// } +//// +//// type ConcreteComponent = +//// | ComponentOptions +//// | FunctionalComponent; +//// +//// type Component = ConcreteComponent; +//// +//// type WithInstallPlugin = { _prefix?: string }; +//// +//// +//// /**/ +//// export function withInstall( +//// component: C | C[], +//// target?: T, +//// ): string { +//// const componentWithInstall = (target ?? component) as T; +//// const components = Array.isArray(component) ? component : [component]; +//// +//// const { name } = components[0]; +//// if (name) { +//// return name; +//// } +//// +//// return ""; +//// } + +verify.noErrors(); + +goTo.marker(); +edit.insert("type C = Component['name']"); + +verify.noErrors(); \ No newline at end of file