From b754fc393738ae05aad136324a0dc78787745644 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 8 Apr 2024 10:58:14 -0700 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#57778=20(fix=20?= =?UTF-8?q?type=20import=20check=20for=20default-i...)=20into=20release-5.?= =?UTF-8?q?4=20(#58116)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lyu, Wei-Da <36730922+jasonlyu123@users.noreply.github.com> --- src/services/completions.ts | 3 +- tests/cases/fourslash/jsFileImportNoTypes2.ts | 59 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/jsFileImportNoTypes2.ts 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/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, + } +}); From 38a7c0587df926957d3a6e808c62c6332665572d Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 8 Apr 2024 11:23:02 -0700 Subject: [PATCH 2/6] release-5.4: Always set node-version for setup-node (#58117) --- .github/workflows/accept-baselines-fix-lints.yaml | 2 ++ .github/workflows/new-release-branch.yaml | 2 ++ .github/workflows/nightly.yaml | 1 + .github/workflows/release-branch-artifact.yaml | 2 ++ .github/workflows/rich-navigation.yml | 2 ++ .github/workflows/set-version.yaml | 2 ++ .github/workflows/sync-branch.yaml | 2 ++ .github/workflows/twoslash-repros.yaml | 2 ++ 8 files changed, 15 insertions(+) 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 }} From 892936f4a18ded0216ae1c805a9890ebb8572fe3 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 9 Apr 2024 12:10:17 -0700 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#58083=20(Don't?= =?UTF-8?q?=20propagate=20partial=20union/inter...)=20into=20release-5.4?= =?UTF-8?q?=20(#58136)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Anders Hejlsberg --- src/compiler/checker.ts | 8 ++-- ...ialUnionPropertyCacheInconsistentErrors.ts | 45 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/partialUnionPropertyCacheInconsistentErrors.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 175caa9eef16e..c3d194211c56a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14788,8 +14788,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 +14798,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/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 From 71b2f84741f94e1414e41af8c65293a030d39945 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 9 Apr 2024 22:14:13 +0000 Subject: [PATCH 4/6] Bump version to 5.4.5 and LKG --- lib/tsc.js | 6 +++--- lib/tsserver.js | 9 +++++---- lib/typescript.js | 9 +++++---- lib/typingsInstaller.js | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/compiler/corePublic.ts | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index eb9b776f9c9d8..65842cbb9ff2e 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 = []; @@ -55510,13 +55510,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..d704e03c5e9c1 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"; @@ -60254,13 +60254,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 +160459,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..8668f6089c8c7 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"; @@ -58009,13 +58009,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 +159682,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/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. From 9f33bf1cd586a4028928d30b1bfe521788ec4da4 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 9 Apr 2024 18:38:50 -0700 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#58098=20(Fix=20?= =?UTF-8?q?constraints=20of=20nested=20homomorph...)=20into=20release-5.4?= =?UTF-8?q?=20(#58118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Anders Hejlsberg --- src/compiler/checker.ts | 18 ++++--- .../homomorphicMappedTypeNesting.symbols | 51 +++++++++++++++++++ .../homomorphicMappedTypeNesting.types | 25 +++++++++ .../compiler/homomorphicMappedTypeNesting.ts | 16 ++++++ 4 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/homomorphicMappedTypeNesting.symbols create mode 100644 tests/baselines/reference/homomorphicMappedTypeNesting.types create mode 100644 tests/cases/compiler/homomorphicMappedTypeNesting.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c3d194211c56a..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; 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>>; From 27bcd4cb5a98bce46c9cdd749752703ead021a4b Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 10 Apr 2024 01:40:12 +0000 Subject: [PATCH 6/6] Update LKG --- lib/tsc.js | 10 ++++------ lib/tsserver.js | 10 ++++------ lib/typescript.js | 10 ++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index 65842cbb9ff2e..f4e4fed2bc00f 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -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; diff --git a/lib/tsserver.js b/lib/tsserver.js index d704e03c5e9c1..3f1ce62663e3c 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -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; diff --git a/lib/typescript.js b/lib/typescript.js index 8668f6089c8c7..22053b17844ef 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -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; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy