Skip to content

Commit e4c2ace

Browse files
authored
Merge pull request #587 from reduxjs/feature/ts-4.9-compat
2 parents f53eb41 + 11ed107 commit e4c2ace

File tree

13 files changed

+365
-230
lines changed

13 files changed

+365
-230
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"@typescript-eslint/no-explicit-any": "off",
4646
"@typescript-eslint/no-unused-vars": "off",
4747
"@typescript-eslint/no-non-null-assertion": "off",
48-
"@typescript-eslint/no-shadow": ["error"],
48+
"@typescript-eslint/no-shadow": ["off"],
4949
"@typescript-eslint/no-use-before-define": ["error"],
5050
"@typescript-eslint/ban-types": "off",
5151
"prefer-rest-params": "off",

.github/workflows/build-and-test-types.yml

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
runs-on: ubuntu-latest
88
strategy:
99
matrix:
10-
node: ['14.x']
10+
node: ['16.x']
1111

1212
steps:
1313
- name: Checkout code
@@ -16,7 +16,7 @@ jobs:
1616
- name: Set up Node
1717
uses: actions/setup-node@v2
1818
with:
19-
node-version: 14.x
19+
node-version: 16.x
2020
cache: 'yarn'
2121

2222
- name: Install dependencies
@@ -47,8 +47,8 @@ jobs:
4747
strategy:
4848
fail-fast: false
4949
matrix:
50-
node: ['14.x']
51-
ts: ['4.2', '4.3', '4.4', '4.5', '4.6', 'next']
50+
node: ['16.x']
51+
ts: ['4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9.2-rc']
5252
steps:
5353
- name: Checkout repo
5454
uses: actions/checkout@v2
@@ -62,15 +62,24 @@ jobs:
6262
- name: Install deps
6363
run: yarn install
6464

65-
- name: Install TypeScript ${{ matrix.ts }}
66-
run: yarn add typescript@${{ matrix.ts }}
67-
65+
# Build with the actual TS version in the repo
6866
- name: Pack
6967
run: yarn build && yarn pack
7068

7169
- name: Install build artifact
7270
run: yarn add ./package.tgz
7371

72+
# Then install the specific version to test against
73+
- name: Install TypeScript ${{ matrix.ts }}
74+
run: yarn add --dev typescript@${{ matrix.ts }}
75+
76+
- name: 'Remove source to ensure packaged types are used'
77+
run: rm -rf src
78+
79+
# Remove config line that points "reselect" to the `src` folder,
80+
# so that the typetest will use the installed version instead
81+
- run: sed -i -e /@remap-prod-remove-line/d ./typescript_test/tsconfig.json
82+
7483
- name: Test types
7584
run: |
7685
./node_modules/.bin/tsc --version

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"typesVersions": {
1111
"<4.2": {
1212
"*": [
13-
"./src/typesVersions/ts4.1/index.d.ts"
13+
"./src/legacyTypes/ts4.1/index.d.ts"
1414
]
1515
}
1616
},
@@ -26,7 +26,7 @@
2626
},
2727
"scripts": {
2828
"build:commonjs": "cross-env BABEL_ENV=commonjs babel src/*.ts --ignore src/types.ts --extensions .ts --out-dir lib ",
29-
"build:es": "babel src/*.ts --ignore src/types.ts --extensions .ts --out-dir es",
29+
"build:es": "babel src/*.ts --ignore src/types.ts --extensions .ts --out-dir es && cp src/versionedTypes/package.dist.json es/versionedTypes/package.json",
3030
"build:umd": "cross-env NODE_ENV=development rollup -c -o dist/reselect.js",
3131
"build:umd:min": "cross-env NODE_ENV=production rollup -c -o dist/reselect.min.js",
3232
"build:types": "tsc",
@@ -62,7 +62,7 @@
6262
"@babel/preset-typescript": "^7.15.0",
6363
"@babel/register": "^7.15.3",
6464
"@microsoft/api-extractor": "^7.18.16",
65-
"@reduxjs/toolkit": "^1.6.2",
65+
"@reduxjs/toolkit": "^1.9.0-rc.1",
6666
"@rollup/plugin-babel": "^5.3.0",
6767
"@rollup/plugin-commonjs": "^21.0.1",
6868
"@rollup/plugin-node-resolve": "^13.0.6",
@@ -87,13 +87,13 @@
8787
"mocha": "^9.1.3",
8888
"ncp": "^2.0.0",
8989
"nyc": "^15.1.0",
90-
"prettier": "^2.4.1",
90+
"prettier": "^2.7.1",
9191
"react-redux": "^7.2.6",
9292
"rimraf": "^3.0.2",
9393
"rollup": "^2.58.0",
9494
"rollup-plugin-terser": "^7.0.2",
9595
"ts-jest": "27.0.7",
9696
"tslint": "6.1.3",
97-
"typescript": "^4.4.0"
97+
"typescript": "4.8.3"
9898
}
9999
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
export type {
1616
Selector,
1717
GetParamsFromSelectors,
18+
GetStateFromSelectors,
1819
OutputSelector,
1920
EqualityFn,
2021
SelectorArray,
File renamed without changes.

src/types.ts

Lines changed: 17 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { MergeParameters } from './versionedTypes'
2+
export type { MergeParameters } from './versionedTypes'
3+
14
/*
25
*
36
* Reselect Data Types
@@ -94,56 +97,6 @@ export type GetParamsFromSelectors<
9497
RemainingItems extends readonly unknown[] = Tail<MergeParameters<S>>
9598
> = RemainingItems
9699

97-
/** Given a set of input selectors, extracts the intersected parameters to determine
98-
* what values can actually be passed to all of the input selectors at once
99-
* WARNING: "you are not expected to understand this" :)
100-
*/
101-
export type MergeParameters<
102-
// The actual array of input selectors
103-
T extends readonly UnknownFunction[],
104-
// Given those selectors, we do several transformations on the types in sequence:
105-
// 1) Extract "the type of parameters" for each input selector, so that we now have
106-
// a tuple of all those parameters
107-
ParamsArrays extends readonly any[][] = ExtractParams<T>,
108-
// 2) Transpose the parameter tuples.
109-
// Originally, we have nested arrays with "all params from input", "from input 2", etc:
110-
// `[ [i1a, i1b, i1c], [i2a, i2b, i2c], [i3a, i3b, i3c] ],
111-
// In order to intersect the params at each index, we need to transpose them so that
112-
// we have "all the first args", "all the second args", and so on:
113-
// `[ [i1a, i2a, i3a], [i1b, i2b, i3b], [i1c, i2c, i3c] ]
114-
// Unfortunately, this step also turns the arrays into a union, and weirder, it is
115-
// a union of all possible combinations for all input functions, so there's duplicates.
116-
TransposedArrays = Transpose<ParamsArrays>,
117-
// 3) Turn the union of arrays back into a nested tuple. Order does not matter here.
118-
TuplifiedArrays extends any[] = TuplifyUnion<TransposedArrays>,
119-
// 4) Find the longest params array out of the ones we have.
120-
// Note that this is actually the _nested_ data we wanted out of the transpose step,
121-
// so it has all the right pieces we need.
122-
LongestParamsArray extends readonly any[] = LongestArray<TuplifiedArrays>
123-
> =
124-
// After all that preparation work, we can actually do parameter extraction.
125-
// These steps work somewhat inside out (jump ahead to the middle):
126-
// 11) Finally, after all that, run a shallow expansion on the values to make the user-visible
127-
// field details more readable when viewing the selector's type in a hover box.
128-
ExpandItems<
129-
// 10) Tuples can have field names attached, and it seems to work better to remove those
130-
RemoveNames<{
131-
// 5) We know the longest params array has N args. Loop over the indices of that array.
132-
// 6) For each index, do a check to ensure that we're _only_ checking numeric indices,
133-
// not any field names for array functions like `slice()`
134-
[index in keyof LongestParamsArray]: LongestParamsArray[index] extends LongestParamsArray[number]
135-
? // 9) Any object types that were intersected may have had
136-
IgnoreInvalidIntersections<
137-
// 8) Then, intersect all of the parameters for this arg together.
138-
IntersectAll<
139-
// 7) Since this is a _nested_ array, extract the right sub-array for this index
140-
LongestParamsArray[index]
141-
>
142-
>
143-
: never
144-
}>
145-
>
146-
147100
/*
148101
*
149102
* Reselect Internal Utility Types
@@ -153,28 +106,11 @@ export type MergeParameters<
153106
/** Any function with arguments */
154107
export type UnknownFunction = (...args: any[]) => any
155108

156-
/** An object with no fields */
157-
type EmptyObject = {
158-
[K in any]: never
159-
}
160-
161-
type IgnoreInvalidIntersections<T> = T extends EmptyObject ? never : T
162-
163-
/** Extract the parameters from all functions as a tuple */
164-
export type ExtractParams<T extends readonly UnknownFunction[]> = {
165-
[index in keyof T]: T[index] extends T[number] ? Parameters<T[index]> : never
166-
}
167-
168109
/** Extract the return type from all functions as a tuple */
169110
export type ExtractReturnType<T extends readonly UnknownFunction[]> = {
170111
[index in keyof T]: T[index] extends T[number] ? ReturnType<T[index]> : never
171112
}
172113

173-
/** Recursively expand all fields in an object for easier reading */
174-
export type ExpandItems<T extends readonly unknown[]> = {
175-
[index in keyof T]: T[index] extends T[number] ? Expand<T[index]> : never
176-
}
177-
178114
/** First item in an array */
179115
export type Head<T> = T extends [any, ...any[]] ? T[0] : never
180116
/** All other items in an array */
@@ -191,58 +127,6 @@ export type List<A = any> = ReadonlyArray<A>
191127

192128
export type Has<U, U1> = [U1] extends [U] ? 1 : 0
193129

194-
/** Select the longer of two arrays */
195-
export type Longest<L extends List, L1 extends List> = L extends unknown
196-
? L1 extends unknown
197-
? { 0: L1; 1: L }[Has<keyof L, keyof L1>]
198-
: never
199-
: never
200-
201-
/** Recurse over a nested array to locate the longest one.
202-
* Acts like a type-level `reduce()`
203-
*/
204-
export type LongestArray<S extends readonly any[][]> =
205-
// If this isn't a tuple, all indices are the same, we can't tell a difference
206-
IsTuple<S> extends '0'
207-
? // so just return the type of the first item
208-
S[0]
209-
: // If there's two nested arrays remaining, compare them
210-
S extends [any[], any[]]
211-
? Longest<S[0], S[1]>
212-
: // If there's more than two, extract their types, treat the remainder as a smaller array
213-
S extends [any[], any[], ...infer Rest]
214-
? // then compare those two, recurse through the smaller array, and compare vs its result
215-
Longest<
216-
Longest<S[0], S[1]>,
217-
Rest extends any[][] ? LongestArray<Rest> : []
218-
>
219-
: // If there's one item left, return it
220-
S extends [any[]]
221-
? S[0]
222-
: never
223-
224-
/** Recursive type for intersecting together all items in a tuple, to determine
225-
* the final parameter type at a given argument index in the generated selector. */
226-
export type IntersectAll<T extends any[]> = IsTuple<T> extends '0'
227-
? T[0]
228-
: _IntersectAll<T>
229-
230-
type IfJustNullish<T, True, False> = [T] extends [undefined | null]
231-
? True
232-
: False
233-
234-
/** Intersect a pair of types together, for use in parameter type calculation.
235-
* This is made much more complex because we need to correctly handle cases
236-
* where a function has fewer parameters and the type is `undefined`, as well as
237-
* optional params or params that have `null` or `undefined` as part of a union.
238-
*
239-
* If the next type by itself is `null` or `undefined`, we exclude it and return
240-
* the other type. Otherwise, intersect them together.
241-
*/
242-
type _IntersectAll<T, R = unknown> = T extends [infer First, ...infer Rest]
243-
? _IntersectAll<Rest, IfJustNullish<First, R, R & First>>
244-
: R
245-
246130
/*
247131
*
248132
* External/Copied Utility Types
@@ -253,32 +137,22 @@ type _IntersectAll<T, R = unknown> = T extends [infer First, ...infer Rest]
253137
* Source: https://github.com/sindresorhus/type-fest/blob/main/source/union-to-intersection.d.ts
254138
* Reference: https://github.com/microsoft/TypeScript/issues/29594
255139
*/
256-
export type UnionToIntersection<Union> = (
140+
export type UnionToIntersection<Union> =
257141
// `extends unknown` is always going to be the case and is used to convert the
258142
// `Union` into a [distributive conditional
259143
// type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
260-
Union extends unknown
261-
? // The union type is used as the only argument to a function since the union
262-
// of function arguments is an intersection.
263-
(distributedUnion: Union) => void
264-
: // This won't happen.
265-
never
266-
// Infer the `Intersection` type since TypeScript represents the positional
267-
// arguments of unions of functions as an intersection of the union.
268-
) extends (mergedIntersection: infer Intersection) => void
269-
? Intersection
270-
: never
271-
272-
/**
273-
* Removes field names from a tuple
274-
* Source: https://stackoverflow.com/a/63571175/62937
275-
*/
276-
type RemoveNames<T extends readonly any[]> = [any, ...T] extends [
277-
any,
278-
...infer U
279-
]
280-
? U
281-
: never
144+
(
145+
Union extends unknown
146+
? // The union type is used as the only argument to a function since the union
147+
// of function arguments is an intersection.
148+
(distributedUnion: Union) => void
149+
: // This won't happen.
150+
never
151+
) extends // Infer the `Intersection` type since TypeScript represents the positional
152+
// arguments of unions of functions as an intersection of the union.
153+
(mergedIntersection: infer Intersection) => void
154+
? Intersection
155+
: never
282156

283157
/**
284158
* Assorted util types for type-level conditional logic
@@ -313,7 +187,7 @@ type LastOf<T> = UnionToIntersection<
313187
: never
314188

315189
// TS4.1+
316-
type TuplifyUnion<
190+
export type TuplifyUnion<
317191
T,
318192
L = LastOf<T>,
319193
N = [T] extends [never] ? true : false
@@ -331,21 +205,6 @@ export type ObjValueTuple<
331205
? ObjValueTuple<T, KT, [...R, T[K & keyof T]]>
332206
: R
333207

334-
/**
335-
* Transposes nested arrays
336-
* Source: https://stackoverflow.com/a/66303933/62937
337-
*/
338-
type Transpose<T> = T[Extract<
339-
keyof T,
340-
T extends readonly any[] ? number : unknown
341-
>] extends infer V
342-
? {
343-
[K in keyof V]: {
344-
[L in keyof T]: K extends keyof T[L] ? T[L][K] : undefined
345-
}
346-
}
347-
: never
348-
349208
/** Utility type to infer the type of "all params of a function except the first", so we can determine what arguments a memoize function accepts */
350209
export type DropFirst<T extends unknown[]> = T extends [unknown, ...infer U]
351210
? U

src/versionedTypes/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { MergeParameters } from './ts47-mergeParameters'

src/versionedTypes/package.dist.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"typesVersions": {
3+
">=4.7": {
4+
"index": [
5+
"./ts47-mergeParameters.d.ts"
6+
]
7+
},
8+
"<4.7": {
9+
"index": [
10+
"./ts46-mergeParameters.d.ts"
11+
]
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)