From 1618532d7ef97c743e97464172af3f5ca187018c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:05:09 -0700 Subject: [PATCH 1/8] First round of jsdoc diff acceptance/documentation --- CHANGES.md | 93 ++++++++++++++++++++++++++++++++++ testdata/submoduleAccepted.txt | 10 +++- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 22f84c3465..718e50b111 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,3 +29,96 @@ Corsa no longer parses the following JSDoc tags with a specific node type. They 2. `@throws` 3. `@author` 4. `@enum` + +## Checker + +### JSDoc Tags + +1. `@type` tags no longer apply to function declarations, and now contextually type functionn expressions instead of applying directly. So this annotation no longer does anything: + +```js + +/** @type {(x: unknown) => asserts x is string } */ +function assertIsString(x) { + if (!(typeof x === "string")) throw new Error(); +} +``` + +Although this one still works via contextual typing: + +```js +/** @typedef {(check: boolean) => asserts check} AssertFunc */ + +/** @type {AssertFunc} */ +const assert = check => { + if (!check) throw new Error(); +} +``` + +A number of things change slightly because of differences between type annotation and contextual typing. + +2. `asserts` annotation for an arrow function must be on the declaring variable, not on the arrow itself. This no longer works: + +```js +/** + * @param {A} a + * @returns { asserts a is B } + */ +const foo = (a) => { + if (/** @type { B } */ (a).y !== 0) throw TypeError(); + return undefined; +}; +``` + +And must be written like this: + +```js +/** + * @type {(a: A) => asserts a is B} + */ +const foo = (a) => { + if (/** @type { B } */ (a).y !== 0) throw TypeError(); + return undefined; +}; +``` + +This is identical to the Typescript rule. + +3. Error messages on async functions that incorrectly return non-Promises now use the same error as TS. + +### Expandos + +1. Exporting `void 0` is no longer ignored as a special case: + +```js +var o = {} +o.y = void 0 +``` + +creates a property `y: undefined` on `o` (which will widen to `y: any` if strictNullChecks is off). + +### CommonJS + +1. Chained exports no longer work: + +```js +exports.x = exports.y = 12 +``` + +Now only exports `x`, not `y` as well. + +2. Exporting `void 0` is no longer ignored as a special case: + +```js +exports.x = void 0 +// several lines later... +exports.x = theRealExport +``` + +3. Type info for `module` shows a property with name of an instead of `exports`: + +```js +module.exports = singleIdentifier +``` + +results in `module: { singleIdentifier: any }` diff --git a/testdata/submoduleAccepted.txt b/testdata/submoduleAccepted.txt index 9fe33a5e08..a427d46674 100644 --- a/testdata/submoduleAccepted.txt +++ b/testdata/submoduleAccepted.txt @@ -1,3 +1,11 @@ # Diff files to instead write to submoduleAccepted as "accepted" changes. +conformance/assertionsAndNonReturningFunctions.types.diff +conformance/assertionTypePredicates2.errors.txt.diff +conformance/assignmentToVoidZero1.errors.txt.diff +conformance/assignmentToVoidZero1.types.diff +conformance/asyncArrowFunction_allowJs.errors.txt.diff +conformance/asyncArrowFunction_allowJs.types.diff +conformance/asyncFunctionDeclaration16_es5.errors.txt.diff +conformance/asyncFunctionDeclaration16_es5.types.diff conformance/node10Alternateresult_noTypes.errors.txt.diff -conformance/node10AlternateResult_noResolution.errors.txt.diff \ No newline at end of file +conformance/node10AlternateResult_noResolution.errors.txt.diff From 44018d143b7374b730fadc77ab9bc66d78e9c65f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 18 Jul 2025 09:28:41 -0700 Subject: [PATCH 2/8] conformance/ round 1 done through checkExportsObjectAssignProperty --- CHANGES.md | 137 ++++++++++++++++++++++++++++++++- testdata/submoduleAccepted.txt | 13 ++++ 2 files changed, 148 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8bb42632f2..7fb90d68d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,13 +24,65 @@ JSDoc types are parsed in normal type annotation position but show a grammar err Corsa no longer parses the following JSDoc tags with a specific node type. They now parse as generic JSDocTag nodes. -1. `@class` +1. `@class`/`@constructor` 2. `@throws` 3. `@author` 4. `@enum` ## Checker +1. When `"strict": false`, Corsa no longer allows omitting arguments for parameters with type `undefined`, `unknown`, or `any`: + + +```js +/** @param {unknown} x */ +function f(x) { return x; } +f(); // Previously allowed, now an error +``` + +`void` can still be omitted, regardless of strict mode: + +```js +/** @param {void} x */ +function f(x) { return x; } +f(); // Still allowed +``` + +### JSDoc Types + +1. JSDoc variadic types are now only synonyms for array types. + +```js +/** @param {...number} ns */ +function sum(...ns) {} +``` + +is equivalent to + + +```js +/** @param {number[]} ns */ +function sum(...ns) {} +``` + +They have no other semantics. + + +2. A variadic type on a parameter no longer makes it a rest parameter. The parameter must use standard rest syntax. + +```js +/** @param {...number} ns */ +function sum(ns) {} +``` + +Must now be written as + +```js +/** @param {...number} ns */ +function sum(...ns) {} +``` + + ### JSDoc Tags 1. `@type` tags no longer apply to function declarations, and now contextually type functionn expressions instead of applying directly. So this annotation no longer does anything: @@ -85,9 +137,17 @@ This is identical to the Typescript rule. 3. Error messages on async functions that incorrectly return non-Promises now use the same error as TS. +4. `@typedef` and `@callback` in a class body are no longer accessible outside the class. +They must be moved outside the class to use them outside the class. + +5. `@class` or `@constructor` does not make a function into a constructor function. + +Corsa ignores `@class` and `@constructor`. +This makes a difference on a function without this-property assignments or associated prototype-function assignments. + ### Expandos -1. Exporting `void 0` is no longer ignored as a special case: +1. Expando assignments of `void 0` are no longer ignored as a special case: ```js var o = {} @@ -96,6 +156,56 @@ o.y = void 0 creates a property `y: undefined` on `o` (which will widen to `y: any` if strictNullChecks is off). +2. A this-property expression with a type annotation in the constructor no longer creates a property: + +```js +class SharedClass { + constructor() { + /** @type {SharedId} */ + this.id; + } +} +``` + +Provide an initializer or use a property declaration in the class body: + +```js +class SharedClass1 { + /** @type {SharedId} */ + id; +} +class SharedClass2 { + constructor() { + /** @type {SharedId} */ + this.id = 1; + } +} +``` + +3. Assigning an object literal to the `prototype` property of a function no longer makes it a constructor function: + +```js +function Foo() {} +Foo.prototype = { + /** @param {number} x */ + bar(x) { + return x; + } +}; +``` + +If you still need to use constructor functions instead of classes, you should declare methods individually on the prototype: + +```js +function Foo() {} +/** @param {number} x */ +Foo.prototype.bar = function(x) { + return x; +}; +``` + +Although classes are a much better way to write this code. + ### CommonJS 1. Chained exports no longer work: @@ -114,6 +224,8 @@ exports.x = void 0 exports.x = theRealExport ``` +This exports `x: undefined` not `x: typeof theRealExport`. + 3. Type info for `module` shows a property with name of an instead of `exports`: ```js @@ -121,3 +233,24 @@ module.exports = singleIdentifier ``` results in `module: { singleIdentifier: any }` + +4. Property access on `require` no longer imports a single property from a module: + +```js +const x = require("y").x +``` + +If you can't configure your package to use ESM syntax, you can use destructuring instead: + +```js +const { x } = require("y") +``` + +5. `Object.defineProperty` on `exports` no longer creates an export: + +```js +Object.defineProperty(exports, "x", { value: 12 }) +``` + +This applies to `module.exports` as well. +Use `exports.x = 12` instead. diff --git a/testdata/submoduleAccepted.txt b/testdata/submoduleAccepted.txt index a427d46674..4acafede98 100644 --- a/testdata/submoduleAccepted.txt +++ b/testdata/submoduleAccepted.txt @@ -7,5 +7,18 @@ conformance/asyncArrowFunction_allowJs.errors.txt.diff conformance/asyncArrowFunction_allowJs.types.diff conformance/asyncFunctionDeclaration16_es5.errors.txt.diff conformance/asyncFunctionDeclaration16_es5.types.diff +conformance/binderUninitializedModuleExportsAssignment.types.diff +conformance/callbackOnConstructor.errors.txt.diff +conformance/callbackOnConstructor.types.diff +conformance/callbackTag2.errors.txt.diff +conformance/callbackTag2.types.diff +conformance/callbackTag4.types.diff +conformance/callbackTagNamespace.types.diff +conformance/callbackTagVariadicType.types.diff +conformance/callOfPropertylessConstructorFunction.errors.txt.diff +conformance/callOfPropertylessConstructorFunction.types.diff +conformance/callWithMissingVoidUndefinedUnknownAnyInJs(strict=false).errors.txt.diff +conformance/checkExportsObjectAssignProperty.errors.txt.diff +conformance/checkExportsObjectAssignProperty.types.diff conformance/node10Alternateresult_noTypes.errors.txt.diff conformance/node10AlternateResult_noResolution.errors.txt.diff From b9f57b46f5334903429f769f067965d32aa77da9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 21 Jul 2025 05:55:18 -0700 Subject: [PATCH 3/8] Done through checkParamTag1 + a little svelte --- CHANGES.md | 60 ++++++++++++++++++++++++++++++++++ testdata/submoduleAccepted.txt | 4 +++ 2 files changed, 64 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 7fb90d68d5..fa48f3cab0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -48,6 +48,18 @@ function f(x) { return x; } f(); // Still allowed ``` +2. Strada's JS-specific rules for inferring type arguments no apply in Corsa. + +Inferred type arguments may change. For example: + +```js +/** @type {any} */ +var x = { a: 1, b: 2 }; +var entries = Object.entries(x); +``` +In Strada, `entries: Array<[string, any]>`. +In Corsa it has type `Array<[string, unknown]>`, the same as in TypeScript. + ### JSDoc Types 1. JSDoc variadic types are now only synonyms for array types. @@ -82,6 +94,18 @@ Must now be written as function sum(...ns) {} ``` +3. The postfix `=` type no longer adds `undefined` even when `strictNullChecks` is off: + +```js +/** @param {number=} x */ +function f(x) { + return x; +} +``` + +will now have `x?: number` not `x?: number | undefined` with `strictNullChecks` off. +Regardless of strictness, it still makes parameters optional when used in a `@param` tag. + ### JSDoc Tags @@ -145,6 +169,42 @@ They must be moved outside the class to use them outside the class. Corsa ignores `@class` and `@constructor`. This makes a difference on a function without this-property assignments or associated prototype-function assignments. +6. `@param` tags now apply to at most one function. + +If they're in a place where they could apply to multiple functions, they apply only to the first one. +If you have `"strict": true`, you will see a noImplicitAny error on the now-untyped parameters. + +```js +/** @param {number} x */ +var f = x => x, g = x => x; +``` + +7. Optional marking on parameter names now makes the parameter both optional and undefined: + +```js +/** @param {number} [x] */ +function f(x) { + return x; +} +``` + +This behaves the same as Typescript's `x?: number` syntax. +Strada makes the parameter optional but does not add `undefined` to the type. + +8. Type assertions with `@type` tags now prevent narrowing of the type. + +```js +/** @param {C | undefined} cu */ +function f(cu) { + if (/** @type {any} */ (cu).undeclaredProperty) { + cu // still has type C | undefined + } +} +``` + +In Strada, `cu` incorrectly narrows to `C` inside the `if` block, unlike with TS assertion syntax. +In Corsa, the behaviour is the same between TS and JS. + ### Expandos 1. Expando assignments of `void 0` are no longer ignored as a special case: diff --git a/testdata/submoduleAccepted.txt b/testdata/submoduleAccepted.txt index 4acafede98..8265de6f8b 100644 --- a/testdata/submoduleAccepted.txt +++ b/testdata/submoduleAccepted.txt @@ -20,5 +20,9 @@ conformance/callOfPropertylessConstructorFunction.types.diff conformance/callWithMissingVoidUndefinedUnknownAnyInJs(strict=false).errors.txt.diff conformance/checkExportsObjectAssignProperty.errors.txt.diff conformance/checkExportsObjectAssignProperty.types.diff +conformance/checkJsdocOnEndOfFile.types.diff +conformance/checkJsdocParamOnVariableDeclaredFunctionExpression.errors.txt.diff +conformance/checkJsdocParamOnVariableDeclaredFunctionExpression.types.diff +conformance/checkParamTag1.types.diff conformance/node10Alternateresult_noTypes.errors.txt.diff conformance/node10AlternateResult_noResolution.errors.txt.diff From 509aadc9eb5c907a1d1e1b1602877dd5fa51274a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 21 Jul 2025 06:15:15 -0700 Subject: [PATCH 4/8] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index fa48f3cab0..824c36cfc0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -48,7 +48,7 @@ function f(x) { return x; } f(); // Still allowed ``` -2. Strada's JS-specific rules for inferring type arguments no apply in Corsa. +2. Strada's JS-specific rules for inferring type arguments no longer apply in Corsa. Inferred type arguments may change. For example: From 257f54d8847a3969407c84970f022fcb20a54bca Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 21 Jul 2025 06:15:39 -0700 Subject: [PATCH 5/8] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 824c36cfc0..692d6612b8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -109,7 +109,7 @@ Regardless of strictness, it still makes parameters optional when used in a `@pa ### JSDoc Tags -1. `@type` tags no longer apply to function declarations, and now contextually type functionn expressions instead of applying directly. So this annotation no longer does anything: +1. `@type` tags no longer apply to function declarations, and now contextually type function expressions instead of applying directly. So this annotation no longer does anything: ```js From 227d57f74175e046ae33994dbd3250848347e05c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 21 Jul 2025 06:15:47 -0700 Subject: [PATCH 6/8] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 692d6612b8..ab1b5a9525 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -286,7 +286,7 @@ exports.x = theRealExport This exports `x: undefined` not `x: typeof theRealExport`. -3. Type info for `module` shows a property with name of an instead of `exports`: +3. Type info for `module` shows a property with name of the export instead of `exports`: ```js module.exports = singleIdentifier From 678d0c9cba3ef751cdc520249420e68730768bbe Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 22 Jul 2025 06:39:47 -0700 Subject: [PATCH 7/8] reformat entries, add important entry at start --- CHANGES.md | 57 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ab1b5a9525..5882d29320 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,7 +31,8 @@ Corsa no longer parses the following JSDoc tags with a specific node type. They ## Checker -1. When `"strict": false`, Corsa no longer allows omitting arguments for parameters with type `undefined`, `unknown`, or `any`: +### Miscellaneous +#### When `"strict": false`, Corsa no longer allows omitting arguments for parameters with type `undefined`, `unknown`, or `any`: ```js @@ -48,7 +49,7 @@ function f(x) { return x; } f(); // Still allowed ``` -2. Strada's JS-specific rules for inferring type arguments no longer apply in Corsa. +#### Strada's JS-specific rules for inferring type arguments no longer apply in Corsa. Inferred type arguments may change. For example: @@ -60,9 +61,23 @@ var entries = Object.entries(x); In Strada, `entries: Array<[string, any]>`. In Corsa it has type `Array<[string, unknown]>`, the same as in TypeScript. +#### Values are no longer resolved as types in JSDoc type positions. + +```js +/** @typedef {FORWARD | BACKWARD} Direction */ +const FORWARD = 1, BACKWARD = 2; +``` + +Must now use `typeof` the same way TS does: + +```js +/** @typedef {typeof FORWARD | typeof BACKWARD} Direction */ +const FORWARD = 1, BACKWARD = 2; +``` + ### JSDoc Types -1. JSDoc variadic types are now only synonyms for array types. +#### JSDoc variadic types are now only synonyms for array types. ```js /** @param {...number} ns */ @@ -80,7 +95,7 @@ function sum(...ns) {} They have no other semantics. -2. A variadic type on a parameter no longer makes it a rest parameter. The parameter must use standard rest syntax. +#### A variadic type on a parameter no longer makes it a rest parameter. The parameter must use standard rest syntax. ```js /** @param {...number} ns */ @@ -94,7 +109,7 @@ Must now be written as function sum(...ns) {} ``` -3. The postfix `=` type no longer adds `undefined` even when `strictNullChecks` is off: +#### The postfix `=` type no longer adds `undefined` even when `strictNullChecks` is off: ```js /** @param {number=} x */ @@ -109,7 +124,7 @@ Regardless of strictness, it still makes parameters optional when used in a `@pa ### JSDoc Tags -1. `@type` tags no longer apply to function declarations, and now contextually type function expressions instead of applying directly. So this annotation no longer does anything: +#### `@type` tags no longer apply to function declarations, and now contextually type function expressions instead of applying directly. So this annotation no longer does anything: ```js @@ -132,7 +147,7 @@ const assert = check => { A number of things change slightly because of differences between type annotation and contextual typing. -2. `asserts` annotation for an arrow function must be on the declaring variable, not on the arrow itself. This no longer works: +#### `asserts` annotation for an arrow function must be on the declaring variable, not on the arrow itself. This no longer works: ```js /** @@ -159,17 +174,17 @@ const foo = (a) => { This is identical to the Typescript rule. -3. Error messages on async functions that incorrectly return non-Promises now use the same error as TS. +#### Error messages on async functions that incorrectly return non-Promises now use the same error as TS. -4. `@typedef` and `@callback` in a class body are no longer accessible outside the class. +#### `@typedef` and `@callback` in a class body are no longer accessible outside the class. They must be moved outside the class to use them outside the class. -5. `@class` or `@constructor` does not make a function into a constructor function. +#### `@class` or `@constructor` does not make a function into a constructor function. Corsa ignores `@class` and `@constructor`. This makes a difference on a function without this-property assignments or associated prototype-function assignments. -6. `@param` tags now apply to at most one function. +#### `@param` tags now apply to at most one function. If they're in a place where they could apply to multiple functions, they apply only to the first one. If you have `"strict": true`, you will see a noImplicitAny error on the now-untyped parameters. @@ -179,7 +194,7 @@ If you have `"strict": true`, you will see a noImplicitAny error on the now-unty var f = x => x, g = x => x; ``` -7. Optional marking on parameter names now makes the parameter both optional and undefined: +#### Optional marking on parameter names now makes the parameter both optional and undefined: ```js /** @param {number} [x] */ @@ -191,7 +206,7 @@ function f(x) { This behaves the same as Typescript's `x?: number` syntax. Strada makes the parameter optional but does not add `undefined` to the type. -8. Type assertions with `@type` tags now prevent narrowing of the type. +#### Type assertions with `@type` tags now prevent narrowing of the type. ```js /** @param {C | undefined} cu */ @@ -207,7 +222,7 @@ In Corsa, the behaviour is the same between TS and JS. ### Expandos -1. Expando assignments of `void 0` are no longer ignored as a special case: +#### Expando assignments of `void 0` are no longer ignored as a special case: ```js var o = {} @@ -216,7 +231,7 @@ o.y = void 0 creates a property `y: undefined` on `o` (which will widen to `y: any` if strictNullChecks is off). -2. A this-property expression with a type annotation in the constructor no longer creates a property: +#### A this-property expression with a type annotation in the constructor no longer creates a property: ```js class SharedClass { @@ -242,7 +257,7 @@ class SharedClass2 { } ``` -3. Assigning an object literal to the `prototype` property of a function no longer makes it a constructor function: +#### Assigning an object literal to the `prototype` property of a function no longer makes it a constructor function: ```js function Foo() {} @@ -268,7 +283,7 @@ Although classes are a much better way to write this code. ### CommonJS -1. Chained exports no longer work: +#### Chained exports no longer work: ```js exports.x = exports.y = 12 @@ -276,7 +291,7 @@ exports.x = exports.y = 12 Now only exports `x`, not `y` as well. -2. Exporting `void 0` is no longer ignored as a special case: +#### Exporting `void 0` is no longer ignored as a special case: ```js exports.x = void 0 @@ -286,7 +301,7 @@ exports.x = theRealExport This exports `x: undefined` not `x: typeof theRealExport`. -3. Type info for `module` shows a property with name of the export instead of `exports`: +#### Type info for `module` shows a property with name of the export instead of `exports`: ```js module.exports = singleIdentifier @@ -294,7 +309,7 @@ module.exports = singleIdentifier results in `module: { singleIdentifier: any }` -4. Property access on `require` no longer imports a single property from a module: +#### Property access on `require` no longer imports a single property from a module: ```js const x = require("y").x @@ -306,7 +321,7 @@ If you can't configure your package to use ESM syntax, you can use destructuring const { x } = require("y") ``` -5. `Object.defineProperty` on `exports` no longer creates an export: +#### `Object.defineProperty` on `exports` no longer creates an export: ```js Object.defineProperty(exports, "x", { value: 12 }) From 665d890b720ca5a98ded34de1ac039c024bd228b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 22 Jul 2025 06:44:53 -0700 Subject: [PATCH 8/8] expand some too-short explanations --- CHANGES.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5882d29320..8de2bf597a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -109,7 +109,10 @@ Must now be written as function sum(...ns) {} ``` -#### The postfix `=` type no longer adds `undefined` even when `strictNullChecks` is off: +#### The postfix `=` type no longer adds `undefined` even when `strictNullChecks` is off + +This is a bug in Strada: it adds `undefined` to the type even when `strictNullChecks` is off. +This bug is fixed in Corsa. ```js /** @param {number=} x */ @@ -301,13 +304,13 @@ exports.x = theRealExport This exports `x: undefined` not `x: typeof theRealExport`. -#### Type info for `module` shows a property with name of the export instead of `exports`: +#### Hover for `module` shows a property with name of the export instead of `exports`: ```js module.exports = singleIdentifier ``` -results in `module: { singleIdentifier: any }` +shows a hover type like `module: { singleIdentifier: any }` #### Property access on `require` no longer imports a single property from a module: