diff --git a/.github/workflows/output_diff.yml b/.github/workflows/output_diff.yml index 6dcafea1c2..74690ee3cd 100644 --- a/.github/workflows/output_diff.yml +++ b/.github/workflows/output_diff.yml @@ -50,11 +50,12 @@ jobs: working-directory: main - name: 'Execute prettier and remove ts-expect-error on PR dist' - run: sed '/@ts-expect-error/d' dist/immutable.es.js | npx prettier --parser=babel > dist/immutable.es.prettier.js + run: npx terser dist/immutable.es.js --comments false | npx prettier --parser=babel > dist/immutable.es.prettier.js + working-directory: pr - name: 'Execute prettier main dist' - run: sed '/@ts-expect-error/d' dist/immutable.es.js | npx prettier --parser=babel > dist/immutable.es.prettier.js + run: npx terser dist/immutable.es.js --comments false | npx prettier --parser=babel > dist/immutable.es.prettier.js working-directory: main - name: 'Output diff' diff --git a/__tests__/MultiRequire.js b/__tests__/MultiRequire.js index 61b4d7c10c..3afa018aab 100644 --- a/__tests__/MultiRequire.js +++ b/__tests__/MultiRequire.js @@ -1,10 +1,8 @@ -// eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef -const Immutable1 = require('../src/Immutable'); +import * as Immutable1 from '../src/Immutable'; jest.resetModules(); -// eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef -const Immutable2 = require('../src/Immutable'); +const Immutable2 = jest.requireActual('../src/Immutable'); describe('MultiRequire', () => { it('might require two different instances of Immutable', () => { diff --git a/eslint.config.mjs b/eslint.config.mjs index 1307f529fa..6fc7ae91d2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -21,6 +21,7 @@ export default tseslint.config( { languageOptions: { globals: globals.browser } }, pluginJs.configs.recommended, importPlugin.flatConfigs.recommended, + importPlugin.flatConfigs.typescript, ...tseslint.configs.recommended, { @@ -48,14 +49,6 @@ export default tseslint.config( }, }, - { - files: ['**/*.{ts,tsx}'], - extends: [ - importPlugin.flatConfigs.recommended, - importPlugin.flatConfigs.typescript, - ], - }, - { files: ['src/*'], rules: { diff --git a/package-lock.json b/package-lock.json index 9e49875912..d15634d7fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@rollup/plugin-commonjs": "28.0.2", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^12.1.2", "@size-limit/esbuild-why": "^8.2.6", "@size-limit/preset-small-lib": "^8.2.6", "@types/jest": "^29.0.0", @@ -48,6 +49,7 @@ "rollup": "4.34.8", "size-limit": "^8.2.6", "transducers-js": "0.4.174", + "tslib": "^2.8.1", "tstyche": "^3.5", "typescript": "5.7", "typescript-eslint": "^8.24.0" @@ -2148,6 +2150,33 @@ } } }, + "node_modules/@rollup/plugin-typescript": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.2.tgz", + "integrity": "sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, "node_modules/@rollup/pluginutils": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", @@ -13779,6 +13808,16 @@ "terser": "^5.17.4" } }, + "@rollup/plugin-typescript": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.2.tgz", + "integrity": "sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + } + }, "@rollup/pluginutils": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", diff --git a/package.json b/package.json index b6b362df88..eb332e8883 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "lint:format": "prettier --check \"{__tests__,src,type-definitions,website/src,perf,resources}/**/*{.js,.mjs,.ts,.tsx,.flow,.css}\"", "lint:js": "eslint", "type-check": "run-s type-check:*", - "type-check:ts": "tsc --project type-definitions/tsconfig.json && tsc --project __tests__/tsconfig.json", + "type-check:ts": "tsc --project tsconfig.src.json && tsc --project type-definitions/tsconfig.json && tsc --project __tests__/tsconfig.json", "type-check:flow": "flow check type-definitions/flow-tests --include-warnings", "build": "run-s build:*", "build:clean": "rimraf dist", @@ -87,6 +87,7 @@ "@rollup/plugin-commonjs": "28.0.2", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^12.1.2", "@size-limit/esbuild-why": "^8.2.6", "@size-limit/preset-small-lib": "^8.2.6", "@types/jest": "^29.0.0", @@ -121,6 +122,7 @@ "rollup": "4.34.8", "size-limit": "^8.2.6", "transducers-js": "0.4.174", + "tslib": "^2.8.1", "tstyche": "^3.5", "typescript": "5.7", "typescript-eslint": "^8.24.0" diff --git a/resources/jestPreprocessor.js b/resources/jestPreprocessor.js index 53d0b36e9a..5ea6aa5036 100644 --- a/resources/jestPreprocessor.js +++ b/resources/jestPreprocessor.js @@ -22,12 +22,13 @@ function transpileJavaScript(src, path) { const buble = require('@rollup/plugin-buble'); const commonjs = require('@rollup/plugin-commonjs'); const json = require('@rollup/plugin-json'); + const typescript = require('@rollup/plugin-typescript'); // same input options as in rollup-config.js const inputOptions = { input: path, onwarn: () => {}, - plugins: [commonjs(), json(), buble()], + plugins: [commonjs(), json(), typescript(), buble()], }; const bundle = await rollup.rollup(inputOptions); @@ -56,11 +57,6 @@ function transpileJavaScript(src, path) { module.exports = { process(src, path) { - if (path.endsWith('__tests__/MultiRequire.js')) { - // exit early for multi-require as we explicitly want to have several instances - return { code: src }; - } - if (path.endsWith('.ts') || path.endsWith('.tsx')) { return { code: transpileTypeScript(src, path) }; } diff --git a/resources/rollup-config.mjs b/resources/rollup-config.mjs index 99c070b8a0..6963235c5d 100644 --- a/resources/rollup-config.mjs +++ b/resources/rollup-config.mjs @@ -3,6 +3,8 @@ import buble from '@rollup/plugin-buble'; import commonjs from '@rollup/plugin-commonjs'; import json from '@rollup/plugin-json'; import terser from '@rollup/plugin-terser'; +// TODO replace @rollup/plugin-typescript with babel after babel migration +import typescript from '@rollup/plugin-typescript'; import copyright from './copyright.mjs'; const SRC_DIR = path.resolve('src'); @@ -11,7 +13,7 @@ const DIST_DIR = path.resolve('dist'); export default [ { input: path.join(SRC_DIR, 'Immutable.js'), - plugins: [commonjs(), json(), buble()], + plugins: [commonjs(), json(), typescript(), buble()], output: [ // umd build { diff --git a/src/is.js b/src/is.ts similarity index 97% rename from src/is.js rename to src/is.ts index 5feda5da5d..f4430c52fd 100644 --- a/src/is.js +++ b/src/is.ts @@ -54,7 +54,7 @@ import { isValueObject } from './predicates/isValueObject'; * All Immutable collections are Value Objects: they implement `equals()` * and `hashCode()`. */ -export function is(valueA, valueB) { +export function is(valueA: unknown, valueB: unknown): boolean { if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) { return true; } diff --git a/src/predicates/isAssociative.js b/src/predicates/isAssociative.js deleted file mode 100644 index dc282c8850..0000000000 --- a/src/predicates/isAssociative.js +++ /dev/null @@ -1,6 +0,0 @@ -import { isKeyed } from './isKeyed'; -import { isIndexed } from './isIndexed'; - -export function isAssociative(maybeAssociative) { - return isKeyed(maybeAssociative) || isIndexed(maybeAssociative); -} diff --git a/src/predicates/isAssociative.ts b/src/predicates/isAssociative.ts new file mode 100644 index 0000000000..e174616f7b --- /dev/null +++ b/src/predicates/isAssociative.ts @@ -0,0 +1,25 @@ +import { isKeyed } from './isKeyed'; +import { isIndexed } from './isIndexed'; +import type { Collection } from '../../type-definitions/immutable'; + +/** + * True if `maybeAssociative` is either a Keyed or Indexed Collection. + * + * ```js + * import { isAssociative, Map, List, Stack, Set } from 'immutable'; + * + * isAssociative([]); // false + * isAssociative({}); // false + * isAssociative(Map()); // true + * isAssociative(List()); // true + * isAssociative(Stack()); // true + * isAssociative(Set()); // false + * ``` + */ +export function isAssociative( + maybeAssociative: unknown +): maybeAssociative is + | Collection.Keyed + | Collection.Indexed { + return isKeyed(maybeAssociative) || isIndexed(maybeAssociative); +} diff --git a/src/predicates/isCollection.js b/src/predicates/isCollection.js deleted file mode 100644 index f76ccf1980..0000000000 --- a/src/predicates/isCollection.js +++ /dev/null @@ -1,6 +0,0 @@ -// Note: value is unchanged to not break immutable-devtools. -export const IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@'; - -export function isCollection(maybeCollection) { - return Boolean(maybeCollection && maybeCollection[IS_COLLECTION_SYMBOL]); -} diff --git a/src/predicates/isCollection.ts b/src/predicates/isCollection.ts new file mode 100644 index 0000000000..738a4614e0 --- /dev/null +++ b/src/predicates/isCollection.ts @@ -0,0 +1,27 @@ +import type { Collection } from '../../type-definitions/immutable'; + +// Note: value is unchanged to not break immutable-devtools. +export const IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@'; + +/** + * True if `maybeCollection` is a Collection, or any of its subclasses. + * + * ```js + * import { isCollection, Map, List, Stack } from 'immutable'; + * + * isCollection([]); // false + * isCollection({}); // false + * isCollection(Map()); // true + * isCollection(List()); // true + * isCollection(Stack()); // true + * ``` + */ +export function isCollection( + maybeCollection: unknown +): maybeCollection is Collection { + return Boolean( + maybeCollection && + // @ts-expect-error: maybeCollection is typed as `{}`, need to change in 6.0 to `maybeCollection && typeof maybeCollection === 'object' && IS_COLLECTION_SYMBOL in maybeCollection` + maybeCollection[IS_COLLECTION_SYMBOL] + ); +} diff --git a/src/predicates/isImmutable.js b/src/predicates/isImmutable.js deleted file mode 100644 index a31433a8b5..0000000000 --- a/src/predicates/isImmutable.js +++ /dev/null @@ -1,6 +0,0 @@ -import { isCollection } from './isCollection'; -import { isRecord } from './isRecord'; - -export function isImmutable(maybeImmutable) { - return isCollection(maybeImmutable) || isRecord(maybeImmutable); -} diff --git a/src/predicates/isImmutable.ts b/src/predicates/isImmutable.ts new file mode 100644 index 0000000000..d01bd03afb --- /dev/null +++ b/src/predicates/isImmutable.ts @@ -0,0 +1,24 @@ +import type { Collection, Record } from '../../type-definitions/immutable'; +import { isCollection } from './isCollection'; +import { isRecord } from './isRecord'; + +/** + * True if `maybeImmutable` is an Immutable Collection or Record. + * + * Note: Still returns true even if the collections is within a `withMutations()`. + * + * ```js + * import { isImmutable, Map, List, Stack } from 'immutable'; + * isImmutable([]); // false + * isImmutable({}); // false + * isImmutable(Map()); // true + * isImmutable(List()); // true + * isImmutable(Stack()); // true + * isImmutable(Map().asMutable()); // true + * ``` + */ +export function isImmutable( + maybeImmutable: unknown +): maybeImmutable is Collection | Record { + return isCollection(maybeImmutable) || isRecord(maybeImmutable); +} diff --git a/src/predicates/isIndexed.js b/src/predicates/isIndexed.js deleted file mode 100644 index 8f059370b4..0000000000 --- a/src/predicates/isIndexed.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@'; - -export function isIndexed(maybeIndexed) { - return Boolean(maybeIndexed && maybeIndexed[IS_INDEXED_SYMBOL]); -} diff --git a/src/predicates/isIndexed.ts b/src/predicates/isIndexed.ts new file mode 100644 index 0000000000..3e20595af5 --- /dev/null +++ b/src/predicates/isIndexed.ts @@ -0,0 +1,27 @@ +import type { Collection } from '../../type-definitions/immutable'; + +export const IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@'; + +/** + * True if `maybeIndexed` is a Collection.Indexed, or any of its subclasses. + * + * ```js + * import { isIndexed, Map, List, Stack, Set } from 'immutable'; + * + * isIndexed([]); // false + * isIndexed({}); // false + * isIndexed(Map()); // false + * isIndexed(List()); // true + * isIndexed(Stack()); // true + * isIndexed(Set()); // false + * ``` + */ +export function isIndexed( + maybeIndexed: unknown +): maybeIndexed is Collection.Indexed { + return Boolean( + maybeIndexed && + // @ts-expect-error: maybeIndexed is typed as `{}`, need to change in 6.0 to `maybeIndexed && typeof maybeIndexed === 'object' && IS_INDEXED_SYMBOL in maybeIndexed` + maybeIndexed[IS_INDEXED_SYMBOL] + ); +} diff --git a/src/predicates/isKeyed.js b/src/predicates/isKeyed.js deleted file mode 100644 index 1113e847cd..0000000000 --- a/src/predicates/isKeyed.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@'; - -export function isKeyed(maybeKeyed) { - return Boolean(maybeKeyed && maybeKeyed[IS_KEYED_SYMBOL]); -} diff --git a/src/predicates/isKeyed.ts b/src/predicates/isKeyed.ts new file mode 100644 index 0000000000..35f7b7e9c8 --- /dev/null +++ b/src/predicates/isKeyed.ts @@ -0,0 +1,26 @@ +import type { Collection } from '../../type-definitions/immutable'; + +export const IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@'; + +/** + * True if `maybeKeyed` is a Collection.Keyed, or any of its subclasses. + * + * ```js + * import { isKeyed, Map, List, Stack } from 'immutable'; + * + * isKeyed([]); // false + * isKeyed({}); // false + * isKeyed(Map()); // true + * isKeyed(List()); // false + * isKeyed(Stack()); // false + * ``` + */ +export function isKeyed( + maybeKeyed: unknown +): maybeKeyed is Collection.Keyed { + return Boolean( + maybeKeyed && + // @ts-expect-error: maybeKeyed is typed as `{}`, need to change in 6.0 to `maybeKeyed && typeof maybeKeyed === 'object' && IS_KEYED_SYMBOL in maybeKeyed` + maybeKeyed[IS_KEYED_SYMBOL] + ); +} diff --git a/src/predicates/isList.js b/src/predicates/isList.js deleted file mode 100644 index 4ccbd52253..0000000000 --- a/src/predicates/isList.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_LIST_SYMBOL = '@@__IMMUTABLE_LIST__@@'; - -export function isList(maybeList) { - return Boolean(maybeList && maybeList[IS_LIST_SYMBOL]); -} diff --git a/src/predicates/isList.ts b/src/predicates/isList.ts new file mode 100644 index 0000000000..080427eb2a --- /dev/null +++ b/src/predicates/isList.ts @@ -0,0 +1,14 @@ +import type { List } from '../../type-definitions/immutable'; + +export const IS_LIST_SYMBOL = '@@__IMMUTABLE_LIST__@@'; + +/** + * True if `maybeList` is a List. + */ +export function isList(maybeList: unknown): maybeList is List { + return Boolean( + maybeList && + // @ts-expect-error: maybeList is typed as `{}`, need to change in 6.0 to `maybeList && typeof maybeList === 'object' && IS_LIST_SYMBOL in maybeList` + maybeList[IS_LIST_SYMBOL] + ); +} diff --git a/src/predicates/isMap.js b/src/predicates/isMap.js deleted file mode 100644 index 6feeb1d173..0000000000 --- a/src/predicates/isMap.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@'; - -export function isMap(maybeMap) { - return Boolean(maybeMap && maybeMap[IS_MAP_SYMBOL]); -} diff --git a/src/predicates/isMap.ts b/src/predicates/isMap.ts new file mode 100644 index 0000000000..ef96c7e138 --- /dev/null +++ b/src/predicates/isMap.ts @@ -0,0 +1,16 @@ +import type { Map } from '../../type-definitions/immutable'; + +export const IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@'; + +/** + * True if `maybeMap` is a Map. + * + * Also true for OrderedMaps. + */ +export function isMap(maybeMap: unknown): maybeMap is Map { + return Boolean( + maybeMap && + // @ts-expect-error: maybeMap is typed as `{}`, need to change in 6.0 to `maybeMap && typeof maybeMap === 'object' && IS_MAP_SYMBOL in maybeMap` + maybeMap[IS_MAP_SYMBOL] + ); +} diff --git a/src/predicates/isOrdered.js b/src/predicates/isOrdered.js deleted file mode 100644 index 0bea375989..0000000000 --- a/src/predicates/isOrdered.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@'; - -export function isOrdered(maybeOrdered) { - return Boolean(maybeOrdered && maybeOrdered[IS_ORDERED_SYMBOL]); -} diff --git a/src/predicates/isOrdered.ts b/src/predicates/isOrdered.ts new file mode 100644 index 0000000000..972d23d0ef --- /dev/null +++ b/src/predicates/isOrdered.ts @@ -0,0 +1,24 @@ +export const IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@'; + +/** + * True if `maybeOrdered` is a Collection where iteration order is well + * defined. True for Collection.Indexed as well as OrderedMap and OrderedSet. + * + * ```js + * import { isOrdered, Map, OrderedMap, List, Set } from 'immutable'; + * + * isOrdered([]); // false + * isOrdered({}); // false + * isOrdered(Map()); // false + * isOrdered(OrderedMap()); // true + * isOrdered(List()); // true + * isOrdered(Set()); // false + * ``` + */ +export function isOrdered(maybeOrdered: unknown): boolean { + return Boolean( + maybeOrdered && + // @ts-expect-error: maybeOrdered is typed as `{}`, need to change in 6.0 to `maybeOrdered && typeof maybeOrdered === 'object' && IS_ORDERED_SYMBOL in maybeOrdered` + maybeOrdered[IS_ORDERED_SYMBOL] + ); +} diff --git a/src/predicates/isOrderedMap.js b/src/predicates/isOrderedMap.js deleted file mode 100644 index 8519acb475..0000000000 --- a/src/predicates/isOrderedMap.js +++ /dev/null @@ -1,6 +0,0 @@ -import { isMap } from './isMap'; -import { isOrdered } from './isOrdered'; - -export function isOrderedMap(maybeOrderedMap) { - return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap); -} diff --git a/src/predicates/isOrderedMap.ts b/src/predicates/isOrderedMap.ts new file mode 100644 index 0000000000..ac56e200b5 --- /dev/null +++ b/src/predicates/isOrderedMap.ts @@ -0,0 +1,12 @@ +import type { OrderedMap } from '../../type-definitions/immutable'; +import { isMap } from './isMap'; +import { isOrdered } from './isOrdered'; + +/** + * True if `maybeOrderedMap` is an OrderedMap. + */ +export function isOrderedMap( + maybeOrderedMap: unknown +): maybeOrderedMap is OrderedMap { + return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap); +} diff --git a/src/predicates/isOrderedSet.js b/src/predicates/isOrderedSet.js deleted file mode 100644 index 77fc68282a..0000000000 --- a/src/predicates/isOrderedSet.js +++ /dev/null @@ -1,6 +0,0 @@ -import { isSet } from './isSet'; -import { isOrdered } from './isOrdered'; - -export function isOrderedSet(maybeOrderedSet) { - return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet); -} diff --git a/src/predicates/isOrderedSet.ts b/src/predicates/isOrderedSet.ts new file mode 100644 index 0000000000..8ac58beb96 --- /dev/null +++ b/src/predicates/isOrderedSet.ts @@ -0,0 +1,12 @@ +import { isSet } from './isSet'; +import { isOrdered } from './isOrdered'; +import type { OrderedSet } from '../../type-definitions/immutable'; + +/** + * True if `maybeOrderedSet` is an OrderedSet. + */ +export function isOrderedSet( + maybeOrderedSet: unknown +): maybeOrderedSet is OrderedSet { + return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet); +} diff --git a/src/predicates/isRecord.js b/src/predicates/isRecord.js deleted file mode 100644 index c23aa3ed83..0000000000 --- a/src/predicates/isRecord.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@'; - -export function isRecord(maybeRecord) { - return Boolean(maybeRecord && maybeRecord[IS_RECORD_SYMBOL]); -} diff --git a/src/predicates/isRecord.ts b/src/predicates/isRecord.ts new file mode 100644 index 0000000000..ff9b1cdde8 --- /dev/null +++ b/src/predicates/isRecord.ts @@ -0,0 +1,14 @@ +import type { Record } from '../../type-definitions/immutable'; + +export const IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@'; + +/** + * True if `maybeRecord` is a Record. + */ +export function isRecord(maybeRecord: unknown): maybeRecord is Record { + return Boolean( + maybeRecord && + // @ts-expect-error: maybeRecord is typed as `{}`, need to change in 6.0 to `maybeRecord && typeof maybeRecord === 'object' && IS_RECORD_SYMBOL in maybeRecord` + maybeRecord[IS_RECORD_SYMBOL] + ); +} diff --git a/src/predicates/isSeq.js b/src/predicates/isSeq.js deleted file mode 100644 index 5292b31647..0000000000 --- a/src/predicates/isSeq.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@'; - -export function isSeq(maybeSeq) { - return Boolean(maybeSeq && maybeSeq[IS_SEQ_SYMBOL]); -} diff --git a/src/predicates/isSeq.ts b/src/predicates/isSeq.ts new file mode 100644 index 0000000000..1b0f26f04a --- /dev/null +++ b/src/predicates/isSeq.ts @@ -0,0 +1,19 @@ +import type { Seq } from '../../type-definitions/immutable'; + +export const IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@'; + +/** + * True if `maybeSeq` is a Seq. + */ +export function isSeq( + maybeSeq: unknown +): maybeSeq is + | Seq.Indexed + | Seq.Keyed + | Seq.Set { + return Boolean( + maybeSeq && + // @ts-expect-error: maybeSeq is typed as `{}`, need to change in 6.0 to `maybeSeq && typeof maybeSeq === 'object' && MAYBE_SEQ_SYMBOL in maybeSeq` + maybeSeq[IS_SEQ_SYMBOL] + ); +} diff --git a/src/predicates/isSet.js b/src/predicates/isSet.js deleted file mode 100644 index 5c321e3cf9..0000000000 --- a/src/predicates/isSet.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@'; - -export function isSet(maybeSet) { - return Boolean(maybeSet && maybeSet[IS_SET_SYMBOL]); -} diff --git a/src/predicates/isSet.ts b/src/predicates/isSet.ts new file mode 100644 index 0000000000..a9a59fe71c --- /dev/null +++ b/src/predicates/isSet.ts @@ -0,0 +1,16 @@ +import type { Set } from '../../type-definitions/immutable'; + +export const IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@'; + +/** + * True if `maybeSet` is a Set. + * + * Also true for OrderedSets. + */ +export function isSet(maybeSet: unknown): maybeSet is Set { + return Boolean( + maybeSet && + // @ts-expect-error: maybeSet is typed as `{}`, need to change in 6.0 to `maybeSeq && typeof maybeSet === 'object' && MAYBE_SET_SYMBOL in maybeSet` + maybeSet[IS_SET_SYMBOL] + ); +} diff --git a/src/predicates/isStack.js b/src/predicates/isStack.js deleted file mode 100644 index 9922470ca7..0000000000 --- a/src/predicates/isStack.js +++ /dev/null @@ -1,5 +0,0 @@ -export const IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@'; - -export function isStack(maybeStack) { - return Boolean(maybeStack && maybeStack[IS_STACK_SYMBOL]); -} diff --git a/src/predicates/isStack.ts b/src/predicates/isStack.ts new file mode 100644 index 0000000000..b62768f88e --- /dev/null +++ b/src/predicates/isStack.ts @@ -0,0 +1,14 @@ +import type { Stack } from '../../type-definitions/immutable'; + +export const IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@'; + +/** + * True if `maybeStack` is a Stack. + */ +export function isStack(maybeStack: unknown): maybeStack is Stack { + return Boolean( + maybeStack && + // @ts-expect-error: maybeStack is typed as `{}`, need to change in 6.0 to `maybeStack && typeof maybeStack === 'object' && MAYBE_STACK_SYMBOL in maybeStack` + maybeStack[IS_STACK_SYMBOL] + ); +} diff --git a/src/predicates/isValueObject.js b/src/predicates/isValueObject.js deleted file mode 100644 index 94a1a6d646..0000000000 --- a/src/predicates/isValueObject.js +++ /dev/null @@ -1,7 +0,0 @@ -export function isValueObject(maybeValue) { - return Boolean( - maybeValue && - typeof maybeValue.equals === 'function' && - typeof maybeValue.hashCode === 'function' - ); -} diff --git a/src/predicates/isValueObject.ts b/src/predicates/isValueObject.ts new file mode 100644 index 0000000000..f603b517ea --- /dev/null +++ b/src/predicates/isValueObject.ts @@ -0,0 +1,18 @@ +import type { ValueObject } from '../../type-definitions/immutable'; + +/** + * True if `maybeValue` is a JavaScript Object which has *both* `equals()` + * and `hashCode()` methods. + * + * Any two instances of *value objects* can be compared for value equality with + * `Immutable.is()` and can be used as keys in a `Map` or members in a `Set`. + */ +export function isValueObject(maybeValue: unknown): maybeValue is ValueObject { + return Boolean( + maybeValue && + // @ts-expect-error: maybeValue is typed as `{}` + typeof maybeValue.equals === 'function' && + // @ts-expect-error: maybeValue is typed as `{}` + typeof maybeValue.hashCode === 'function' + ); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..b0fa1baad1 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + /* Base Options: */ + "esModuleInterop": true, + "skipLibCheck": true, + "target": "es2022", + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "verbatimModuleSyntax": true, + /* Strictness */ + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + /* If NOT transpiling with TypeScript: */ + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + /* If your code runs in the DOM: */ + "lib": ["es2022", "dom", "dom.iterable"] + } +} diff --git a/tsconfig.src.json b/tsconfig.src.json new file mode 100644 index 0000000000..ae550d9ff2 --- /dev/null +++ b/tsconfig.src.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/Immutable.js"] +}