/
required-deep.ts
119 lines (114 loc) · 4.91 KB
/
required-deep.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import {expectType} from 'tsd';
import {expectTypeOf} from 'expect-type';
import type {RequiredDeep} from '../index';
type Foo = {
baz?: string | undefined;
bar?: {
function?: ((...args: any[]) => void) | undefined;
functionFixedArity?: ((arg1: unknown, arg2: unknown) => void);
functionWithOverload?: {
(arg: number): string;
(arg1: string, arg2: number): number;
};
namespace?: {
(arg: number): string;
key: string | undefined;
};
namespaceWithOverload: {
(arg: number): string;
(arg1: string, arg2: number): number;
key: string | undefined;
};
object?: {key?: 'value'} | undefined;
string?: string | undefined;
number?: number | undefined;
boolean?: false | undefined;
date?: Date | undefined;
regexp?: RegExp | undefined;
symbol?: Symbol | undefined;
null?: null | undefined;
undefined?: undefined;
map?: Map<string | undefined, string | undefined>;
set?: Set<string | undefined>;
array?: Array<string | undefined>;
tuple?: ['foo' | undefined] | undefined;
readonlyMap?: ReadonlyMap<string | undefined, string | undefined>;
readonlySet?: ReadonlySet<string | undefined>;
readonlyArray?: ReadonlyArray<string | undefined>;
readonlyTuple?: readonly ['foo' | undefined] | undefined;
weakMap?: WeakMap<{key: string | undefined}, string | undefined>;
weakSet?: WeakSet<{key: string | undefined}>;
promise?: Promise<string | undefined>;
};
};
type FooRequired = {
baz: string;
bar: {
function: (...args: any[]) => void;
functionFixedArity: (arg1: unknown, arg2: unknown) => void;
functionWithOverload: {
(arg: number): string;
(arg1: string, arg2: number): number;
};
namespace: {
(arg: number): string;
key: string;
};
namespaceWithOverload: {
(arg: number): string;
(arg1: string, arg2: number): number;
key: string;
};
object: {key: 'value'};
string: string;
number: number;
boolean: false;
date: Date;
regexp: RegExp;
symbol: Symbol;
null: null;
undefined: never;
map: Map<string, string>;
set: Set<string>;
array: string[];
tuple: ['foo'];
readonlyMap: ReadonlyMap<string, string>;
readonlySet: ReadonlySet<string>;
readonlyArray: readonly string[];
readonlyTuple: readonly ['foo'];
weakMap: WeakMap<{key: string}, string>;
weakSet: WeakSet<{key: string}>;
promise: Promise<string>;
};
};
type FooBar = Exclude<Foo['bar'], undefined>;
type FooRequiredBar = FooRequired['bar'];
expectTypeOf<RequiredDeep<Foo>>().toEqualTypeOf<FooRequired>();
expectTypeOf<RequiredDeep<FooBar['function']>>().toEqualTypeOf<FooRequiredBar['function']>();
expectTypeOf<RequiredDeep<FooBar['functionFixedArity']>>().toEqualTypeOf<FooRequiredBar['functionFixedArity']>();
expectTypeOf<RequiredDeep<FooBar['object']>>().toEqualTypeOf<FooRequiredBar['object']>();
expectTypeOf<RequiredDeep<FooBar['string']>>().toEqualTypeOf<FooRequiredBar['string']>();
expectTypeOf<RequiredDeep<FooBar['number']>>().toEqualTypeOf<FooRequiredBar['number']>();
expectTypeOf<RequiredDeep<FooBar['boolean']>>().toEqualTypeOf<FooRequiredBar['boolean']>();
expectTypeOf<RequiredDeep<FooBar['date']>>().toEqualTypeOf<FooRequiredBar['date']>();
expectTypeOf<RequiredDeep<FooBar['regexp']>>().toEqualTypeOf<FooRequiredBar['regexp']>();
expectTypeOf<RequiredDeep<FooBar['map']>>().toEqualTypeOf<FooRequiredBar['map']>();
expectTypeOf<RequiredDeep<FooBar['set']>>().toEqualTypeOf<FooRequiredBar['set']>();
expectTypeOf<RequiredDeep<FooBar['array']>>().toEqualTypeOf<FooRequiredBar['array']>();
expectTypeOf<RequiredDeep<FooBar['tuple']>>().toEqualTypeOf<FooRequiredBar['tuple']>();
expectTypeOf<RequiredDeep<FooBar['readonlyMap']>>().toEqualTypeOf<FooRequiredBar['readonlyMap']>();
expectTypeOf<RequiredDeep<FooBar['readonlySet']>>().toEqualTypeOf<FooRequiredBar['readonlySet']>();
expectTypeOf<RequiredDeep<FooBar['readonlyArray']>>().toEqualTypeOf<FooRequiredBar['readonlyArray']>();
expectTypeOf<RequiredDeep<FooBar['readonlyTuple']>>().toEqualTypeOf<FooRequiredBar['readonlyTuple']>();
expectTypeOf<RequiredDeep<FooBar['weakMap']>>().toEqualTypeOf<FooRequiredBar['weakMap']>();
expectTypeOf<RequiredDeep<FooBar['weakSet']>>().toEqualTypeOf<FooRequiredBar['weakSet']>();
expectTypeOf<RequiredDeep<FooBar['promise']>>().toEqualTypeOf<FooRequiredBar['promise']>();
expectTypeOf<RequiredDeep<FooBar['namespace']>>().toEqualTypeOf<FooRequiredBar['namespace']>();
expectTypeOf<RequiredDeep<FooBar['undefined']>>().toBeNever();
expectTypeOf<RequiredDeep<FooBar['null']>>().toEqualTypeOf<FooRequiredBar['null']>();
// These currently need to be left alone due to TypeScript limitations.
// @see https://github.com/microsoft/TypeScript/issues/29732
expectType<string>(({} as unknown as RequiredDeep<FooBar['functionWithOverload']>)(0));
expectType<number>(({} as unknown as RequiredDeep<FooBar['functionWithOverload']>)('foo', 0));
expectType<string>(({} as unknown as RequiredDeep<FooBar['namespaceWithOverload']>)(0));
expectType<number>(({} as unknown as RequiredDeep<FooBar['namespaceWithOverload']>)('foo', 0));