Skip to content

Commit 2e56c72

Browse files
authored
Merge pull request #88 from andnp/ExtendsUnknown
fix: head off breaking change in ts@next
2 parents 222befe + d95b27d commit 2e56c72

15 files changed

+53
-149
lines changed

README.md

+5-39
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ npm install --save-dev simplytyped
1717

1818
**[Objects](#objects)**
1919

20-
[AllKeys](#allkeys) - [AllRequired](#allrequired) - [CombineObjects](#combineobjects) - [DeepPartial](#deeppartial) - [DeepReadonly](#deepreadonly) - [DiffKeys](#diffkeys) - [GetKey](#getkey) - [HasKey](#haskey) - [Intersect](#intersect) - [Keys](#keys) - [KeysByType](#keysbytype) - [Merge](#merge) - [ObjectKeys](#objectkeys) - [ObjectType](#objecttype) - [Omit](#omit) - [Optional](#optional) - [Overwrite](#overwrite) - [PlainObject](#plainobject) - [PureKeys](#purekeys) - [Required](#required) - [SharedKeys](#sharedkeys) - [StrictUnion](#strictunion) - [StringKeys](#stringkeys) - [TaggedObject](#taggedobject) - [UnionizeProperties](#unionizeproperties) - [UnionKeys](#unionkeys)
20+
[AllKeys](#allkeys) - [AllRequired](#allrequired) - [CombineObjects](#combineobjects) - [DeepPartial](#deeppartial) - [DeepReadonly](#deepreadonly) - [DiffKeys](#diffkeys) - [GetKey](#getkey) - [HasKey](#haskey) - [Intersect](#intersect) - [KeysByType](#keysbytype) - [Merge](#merge) - [ObjectKeys](#objectkeys) - [ObjectType](#objecttype) - [Omit](#omit) - [Optional](#optional) - [Overwrite](#overwrite) - [PlainObject](#plainobject) - [PureKeys](#purekeys) - [Required](#required) - [SharedKeys](#sharedkeys) - [StrictUnion](#strictunion) - [StringKeys](#stringkeys) - [TaggedObject](#taggedobject) - [UnionizeProperties](#unionizeproperties) - [UnionKeys](#unionkeys)
2121

2222
**[Utils](#utils)**
2323

24-
[NoInfer](#noinfer) - [Nominal](#nominal) - [Nullable](#nullable) - [PromiseOr](#promiseor) - [Unknown](#unknown)
24+
[NoInfer](#noinfer) - [Nominal](#nominal) - [Nullable](#nullable) - [PromiseOr](#promiseor)
2525

2626
**[Functions](#functions)**
2727

2828
[AnyFunc](#anyfunc) - [ArgsAsTuple](#argsastuple) - [ConstructorFunction](#constructorfunction) - [OverwriteReturn](#overwritereturn) - [Predicate](#predicate)
2929

3030
**[Strings](#strings)**
3131

32-
[Diff](#diff) - [DropString](#dropstring) - [StringEqual](#stringequal) - [UnionContains](#unioncontains)
32+
[DropString](#dropstring) - [StringEqual](#stringequal) - [UnionContains](#unioncontains)
3333

3434
**[Tuples](#tuples)**
3535

@@ -221,7 +221,7 @@ test('Can make an object with functions readonly', t => {
221221

222222
### DiffKeys
223223
Gets all of the keys that are different between two objects.
224-
This is a set difference between `Keys<T>` and `Keys<U>`.
224+
This is a set difference between `keyof T` and `keyof U`.
225225
Note that calling this with arguments reversed will have different results.
226226
```ts
227227
test('Can get all keys that are different between objects', t => {
@@ -283,20 +283,6 @@ test('Can get an object with only shared properties', t => {
283283

284284
```
285285

286-
### Keys
287-
No different than `keyof`, but can look a bit nicer when nesting many types deep.
288-
```ts
289-
test('Can get keys from object', t => {
290-
type obj = { x: number, y: string, z: boolean };
291-
type expected = 'x' | 'y' | 'z';
292-
type got = Keys<obj>;
293-
294-
assert<got, expected>(t);
295-
assert<expected, got>(t);
296-
});
297-
298-
```
299-
300286
### KeysByType
301287
Gets all keys that point to a given type.
302288
```ts
@@ -595,10 +581,6 @@ test('Will give back a promise containing given type union the type itself', t =
595581

596582
```
597583

598-
### Unknown
599-
A constant type that mimics an unknowable type.
600-
601-
602584
## Functions
603585

604586
### AnyFunc
@@ -627,7 +609,7 @@ test("Can get a tuple of function's argument types", t => {
627609
type F2 = (x: number, y: string) => any;
628610
type F3 = (x: number, y: string, z: boolean) => any;
629611

630-
type E0 = void[];
612+
type E0 = [];
631613
type E1 = [number];
632614
type E2 = [number, string];
633615
type E3 = [number, string, boolean];
@@ -691,22 +673,6 @@ test('Can build a predicate function with unknown argument types', t => {
691673

692674
## Strings
693675

694-
### Diff
695-
696-
```ts
697-
test('Can get difference between unions of strings', t => {
698-
type a = 'hi' | 'there';
699-
type b = 'hi' | 'my' | 'friend';
700-
701-
type gotA = Diff<a, b>;
702-
type gotB = Diff<b, a>;
703-
704-
assert<gotA, 'there'>(t);
705-
assert<gotB, 'my' | 'friend'>(t);
706-
});
707-
708-
```
709-
710676
### DropString
711677

712678
```ts

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"commitlint": "^7.0.0",
4343
"husky": "^1.0.0",
4444
"ts-node": "^8.0.3",
45-
"tslint": "^5.8.0"
45+
"tslint": "^5.13.0"
4646
},
4747
"ava": {
4848
"files": [

scripts/testTsVersions.sh

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
set -e
22

3-
# skip ts 2.9 because of bug with skipLibCheck
4-
for v in 2.8.4 3.0.3 3.1.6 3.2.2 next; do
3+
for v in 3.0.3 3.1.6 3.2.2 next; do
54
npm install --no-save typescript@$v
65
npm test
76
done

src/impl/objects.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DeepReadonly, Keys, TaggedObject, ObjectKeys } from '../types/objects';
1+
import { DeepReadonly, TaggedObject } from '../types/objects';
22

33
/**
44
* Type guard for any key, `k`.
@@ -17,7 +17,7 @@ export function isKeyOf<T extends object>(obj: T, k: keyof any): k is keyof T {
1717
* @returns an array of keys from `obj`
1818
*/
1919
export function objectKeys<T extends object>(obj: T) {
20-
return Object.keys(obj) as Array<Keys<T>>;
20+
return Object.keys(obj) as Array<keyof T>;
2121
}
2222

2323
/**
@@ -34,7 +34,7 @@ export function Readonly<T extends object>(obj: T): DeepReadonly<T> { return obj
3434
* @param key the name of the "tag" parameter
3535
* @returns `obj` with the inner objects tagged with parameter `key` and the key pointing to that inner object
3636
*/
37-
export function taggedObject<T extends Record<ObjectKeys, object>, K extends string>(obj: T, key: K): TaggedObject<T, K> {
37+
export function taggedObject<T extends Record<keyof any, object>, K extends string>(obj: T, key: K): TaggedObject<T, K> {
3838
const keys = objectKeys(obj);
3939
return keys.reduce((collection: any, k) => {
4040
const inner: any = obj[k];

src/types/functions.ts

+4-20
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,13 @@ export type AnyFunc<R = any> = (...args: any[]) => R;
2121
* @param R the new return value of the function
2222
* @returns the function `F` with new return value `R`
2323
*/
24-
export type OverwriteReturn<F extends AnyFunc, R> =
25-
F extends () => any ? () => R :
26-
F extends (x1: infer X1) => any ? (x1: X1) => R :
27-
F extends (x1: infer X1, x2: infer X2) => any ? (x1: X1, x2: X2) => R :
28-
F extends (x1: infer X1, x2: infer X2, x3: infer X3) => any ? (x1: X1, x2: X2, x3: X3) => R :
29-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4) => any ? (x1: X1, x2: X2, x3: X3, x4: X4) => R :
30-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4, x5: infer X5) => any ? (x1: X1, x2: X2, x3: X3, x4: X4, x5: X5) => R :
31-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4, x5: infer X5, x6: infer X6) => any ? (x1: X1, x2: X2, x3: X3, x4: X4, x5: X5, x6: X6) => R :
32-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4, x5: infer X5, x6: infer X6, x7: infer X7) => any ? (x1: X1, x2: X2, x3: X3, x4: X4, x5: X5, x6: X6, x7: X7) => R :
33-
AnyFunc<R>;
24+
export type OverwriteReturn<F extends Function, R> =
25+
F extends ((...x: infer T) => unknown) ? ((...x: T) => R) : never;
3426

3527
/**
3628
* Returns a tuple type of a functions arguments up to 7.
3729
* @param F a function with up to 7 arguments
3830
* @returns a tuple containing `F`'s argument types
3931
*/
40-
export type ArgsAsTuple<F extends AnyFunc> =
41-
F extends () => any ? void[] :
42-
F extends (x1: infer X1) => any ? [X1] :
43-
F extends (x1: infer X1, x2: infer X2) => any ? [X1, X2] :
44-
F extends (x1: infer X1, x2: infer X2, x3: infer X3) => any ? [X1, X2, X3] :
45-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4) => any ? [X1, X2, X3, X4] :
46-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4, x5: infer X5) => any ? [X1, X2, X3, X4, X5] :
47-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4, x5: infer X5, x6: infer X6) => any ? [X1, X2, X3, X4, X5, X6] :
48-
F extends (x1: infer X1, x2: infer X2, x3: infer X3, x4: infer X4, x5: infer X5, x6: infer X6, x7: infer X7) => any ? [X1, X2, X3, X4, X5, X6, X7] :
49-
any[];
32+
export type ArgsAsTuple<F extends Function> =
33+
F extends ((...x: infer T) => unknown) ? T : never;

src/types/objects.ts

+23-31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import { Diff } from './strings';
21
import { False, True } from './conditionals';
3-
import { AnyFunc } from './functions';
42

53
// -------
64
// Helpers
@@ -16,7 +14,7 @@ export type PlainObject = Record<string, any>;
1614
* @returns An object formed by the key, value pairs of T
1715
*/
1816
export type ObjectType<T> = {
19-
[k in Keys<T>]: T[k];
17+
[k in keyof T]: T[k];
2018
};
2119
/**
2220
* Takes two objects and returns their intersection.
@@ -35,7 +33,7 @@ export type CombineObjects<T extends object, U extends object> = ObjectType<T &
3533
* @param K Key to query object for value
3634
* @returns `T[K]` if the key exists, `never` otherwise
3735
*/
38-
export type GetKey<T, K extends keyof any> = K extends Keys<T> ? T[K] : never;
36+
export type GetKey<T, K extends keyof any> = K extends keyof T ? T[K] : never;
3937

4038
// ----
4139
// Keys
@@ -56,51 +54,45 @@ export type ObjectKeys = keyof any;
5654
* @param T type from which to get keys
5755
* @returns keys of `T` that extend `string`
5856
*/
59-
export type StringKeys<T> = Exclude<Keys<T>, number | symbol>;
60-
/**
61-
* No different than `keyof`, but can look a bit nicer when nesting many types deep.
62-
* @param T type from which to get keys
63-
* @returns keys of `T` that extend `string | number | symbol`
64-
*/
65-
export type Keys<T> = keyof T;
57+
export type StringKeys<T> = Exclude<keyof T, number | symbol>;
6658
/**
6759
* When an object has optional or readonly keys, that information is contained within the key.
6860
* When using optional/readonly keys in another object, they will retain optional/readonly status.
6961
* `PureKeys` will remove the optional/readonly status modifiers from keys.
7062
* @param T type from which to get keys
7163
* @returns keys of `T` without status modifiers (readonly/optional)
7264
*/
73-
export type PureKeys<T> = Record<Keys<T>, Keys<T>>[Keys<T>];
65+
export type PureKeys<T> = Record<keyof T, keyof T>[keyof T];
7466
/**
7567
* Gets all of the keys that are shared between two objects.
7668
* @param T first type from which keys will be pulled
7769
* @param U second type from which keys will be pulled
7870
* @returns the keys that both `T` and `U` have in common.
7971
*/
80-
export type SharedKeys<T, U> = Keys<T> & Keys<U>;
72+
export type SharedKeys<T, U> = keyof T & keyof U;
8173
/**
8274
* Gets all keys between two objects.
8375
* @param T first type from which keys will be pulled
8476
* @param U second type from which keys will be pulled
8577
* @returns the keys of `T` in addition to the keys of `U`
8678
*/
87-
export type AllKeys<T, U> = Keys<T> | Keys<U>;
79+
export type AllKeys<T, U> = keyof T | keyof U;
8880
/**
8981
* Gets all of the keys that are different between two objects.
90-
* This is a set difference between `Keys<T>` and `Keys<U>`.
82+
* This is a set difference between `keyof T` and `keyof U`.
9183
* Note that calling this with arguments reversed will have different results.
9284
* @param T first type from which keys will be pulled
9385
* @param U second type from which keys will be pulled
9486
* @returns keys of `T` minus the keys of `U`
9587
*/
96-
export type DiffKeys<T, U> = Diff<Keys<T>, Keys<U>>;
88+
export type DiffKeys<T, U> = Exclude<keyof T, keyof U>;
9789
/**
9890
* Returns `True` if a key, `K`, is present in a type, `T`, else `False`.
9991
* @param T type to check for existence of key `K`.
10092
* @param K key to query `T` for
10193
* @returns `True` if `K` is a key of `T`. Else `False`.
10294
*/
103-
export type HasKey<T, K extends keyof any> = K extends Keys<T> ? True : False;
95+
export type HasKey<T, K extends keyof any> = K extends keyof T ? True : False;
10496

10597
/**
10698
* @param T the union to get the keys of
@@ -109,7 +101,7 @@ export type HasKey<T, K extends keyof any> = K extends Keys<T> ? True : False;
109101
export type UnionKeys<T>
110102
// Using a conditional here, so that it distributes over members of the union
111103
// See https://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types
112-
= T extends any ? keyof T : never;
104+
= T extends unknown ? keyof T : never;
113105

114106
// -------------
115107
// Manipulations
@@ -119,15 +111,15 @@ export type UnionKeys<T>
119111
* @param T the object whose property values will be unionized
120112
* @returns a union of the right-side values of `T`
121113
*/
122-
export type UnionizeProperties<T extends object> = T[Keys<T>];
114+
export type UnionizeProperties<T extends object> = T[keyof T];
123115
/**
124116
* Gives back an object with listed keys removed.
125117
* This is the opposite of `Pick`.
126118
* @param T the object whose properties will be removed
127119
* @param K the union of keys to remove from `T`
128120
* @returns `T` with the keys `K` removed
129121
*/
130-
export type Omit<T extends object, K extends Keys<T>> = Pick<T, Diff<Keys<T>, K>>;
122+
export type Omit<T extends object, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
131123
/**
132124
* Returns only the shared properties between two objects.
133125
* All shared properties must be the same type.
@@ -161,7 +153,7 @@ export type Merge<T extends object, U extends object> = Overwrite<T, U> & U;
161153
* @returns a record where each key of the record is now the `Key` property of the inner object
162154
*/
163155
export type TaggedObject<T extends Record<keyof any, object>, Key extends keyof any> = {
164-
[K in Keys<T>]: T[K] & Record<Key, K>;
156+
[K in keyof T]: T[K] & Record<Key, K>;
165157
};
166158

167159
// ---------
@@ -174,9 +166,9 @@ export type TaggedObject<T extends Record<keyof any, object>, Key extends keyof
174166
* @returns `Partial<T>` recursively through all properties of `T`
175167
*/
176168
export type DeepPartial<T> = Partial<{
177-
[k in Keys<T>]:
178-
T[k] extends any[] ? Array<DeepPartial<T[k][number]>> :
179-
T[k] extends AnyFunc ? T[k] :
169+
[k in keyof T]:
170+
T[k] extends unknown[] ? Array<DeepPartial<T[k][number]>> :
171+
T[k] extends Function ? T[k] :
180172
T[k] extends object ? DeepPartial<T[k]> :
181173
T[k];
182174
}>;
@@ -186,15 +178,15 @@ export type DeepPartial<T> = Partial<{
186178
* @returns `T` with all fields marked required
187179
*/
188180
export type AllRequired<T extends object> = {
189-
[K in Keys<T>]-?: NonNullable<T[K]>
181+
[K in keyof T]-?: NonNullable<T[K]>
190182
};
191183
/**
192184
* Mark specific keys, `K`, of `T` as required.
193185
* @param T object whose keys will be marked required
194186
* @param K keys of `T` that will be marked required
195187
* @returns `T` with keys, `K`, marked as required
196188
*/
197-
export type Required<T extends object, K extends Keys<T>> = CombineObjects<
189+
export type Required<T extends object, K extends keyof T> = CombineObjects<
198190
{[k in K]-?: NonNullable<T[k]> },
199191
Omit<T, K>
200192
>;
@@ -204,7 +196,7 @@ export type Required<T extends object, K extends Keys<T>> = CombineObjects<
204196
* @param K keys of `T` that will be marked optional
205197
* @returns `T` with keys, `K`, marked as optional
206198
*/
207-
export type Optional<T extends object, K extends Keys<T>> = CombineObjects<
199+
export type Optional<T extends object, K extends keyof T> = CombineObjects<
208200
{[k in K]?: T[k] | undefined },
209201
Omit<T, K>
210202
>;
@@ -214,9 +206,9 @@ export type Optional<T extends object, K extends Keys<T>> = CombineObjects<
214206
* @returns `T` with all keys recursively marked as readonly
215207
*/
216208
export type DeepReadonly<T> = Readonly<{
217-
[k in Keys<T>]:
218-
T[k] extends any[] ? ReadonlyArray<DeepReadonly<T[k][number]>> :
219-
T[k] extends AnyFunc ? T[k] :
209+
[k in keyof T]:
210+
T[k] extends unknown[] ? ReadonlyArray<DeepReadonly<T[k][number]>> :
211+
T[k] extends Function ? T[k] :
220212
T[k] extends object ? DeepReadonly<T[k]> :
221213
T[k];
222214
}>;
@@ -261,6 +253,6 @@ export type StrictUnion<T> = _StrictUnionHelper<T, T>;
261253
// to refer to each individual member of the union
262254
/** no-doc */
263255
export type _StrictUnionHelper<UnionMember, Union> =
264-
UnionMember extends any ?
256+
UnionMember extends unknown ?
265257
UnionMember & Partial<Record<Exclude<UnionKeys<Union>, keyof UnionMember>, never>>
266258
: never;

src/types/predicates.ts

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
11
import { False, True, And, Or, Not } from './conditionals';
2-
import { Keys } from './objects';
3-
import { AnyFunc } from './functions';
42

53
/** no-doc */
64
export type KnownProblemPrototypeKeys = 'toString' | 'toLocaleString' | 'hasOwnProperty' | 'isPrototypeOf' | 'propertyIsEnumerable' | 'constructor' | 'valueOf';
75
/** no-doc */
8-
export type ArrayPrototypeKeys = Keys<any[]>;
6+
export type ArrayPrototypeKeys = keyof unknown[];
97
/** no-doc */
10-
export type NumberPrototypeKeys = Keys<number>;
8+
export type NumberPrototypeKeys = keyof number;
119
/** no-doc */
12-
export type BooleanPrototypeKeys = Keys<false>;
10+
export type BooleanPrototypeKeys = keyof false;
1311
/** no-doc */
14-
export type StringPrototypeKeys = Keys<string>;
12+
export type StringPrototypeKeys = keyof string;
1513
/** no-doc */
16-
export type ObjectPrototypeKeys = Keys<Object>; // tslint:disable-line
14+
export type ObjectPrototypeKeys = keyof Object;
1715
/** no-doc */
18-
export type FunctionPrototypeKeys = Keys<Function>; // tslint:disable-line
16+
export type FunctionPrototypeKeys = keyof Function;
1917

2018
export type IsNever<S extends string> = Not<(Record<S, True> & Record<string, False>)[S]>;
2119
export type IsType<T, X> = X extends T ? True : False;
22-
export type IsArray<T> = T extends any[] ? True : False;
20+
export type IsArray<T> = T extends unknown[] ? True : False;
2321
export type IsNumber<T> = T extends number ? True : False;
2422
export type IsString<T> = T extends string ? True : False;
2523
export type IsFunction<T> =
2624
Or<
27-
T extends AnyFunc ? True : False,
28-
T extends Function ? True : False>; // tslint:disable-line
25+
T extends Function ? True : False,
26+
T extends Function ? True : False>;
2927

3028
export type IsStringFunction<T extends string> = And<IsString<T>, IsNever<T>>;
3129
export type IsBoolean<T> = T extends boolean ? True : False;

0 commit comments

Comments
 (0)