Skip to content

Commit 7602fb0

Browse files
Add Infer type utility (#221)
Co-authored-by: Sindre Sorhus <[email protected]>
1 parent 3728d91 commit 7602fb0

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

readme.md

+14
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,20 @@ ow(
289289

290290
This can be useful for creating your own reusable validators which can be extracted to a separate npm package.
291291

292+
### TypeScript
293+
294+
Ow includes a type utility that lets you to extract a TypeScript type from the given predicate.
295+
296+
```ts
297+
import ow, {Infer} from 'ow';
298+
299+
const userPredicate = ow.object.exactShape({
300+
name: ow.string
301+
});
302+
303+
type User = Infer<typeof userPredicate>;
304+
```
305+
292306
## Maintainers
293307

294308
- [Sindre Sorhus](https://github.com/sindresorhus)

source/index.ts

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@ import test from './test';
1111
*/
1212
export type Main = <T>(value: T, label: string | Function, predicate: BasePredicate<T>, idLabel?: boolean) => void;
1313

14+
/**
15+
Retrieve the type from the given predicate.
16+
17+
@example
18+
```
19+
import ow, {Infer} from 'ow';
20+
21+
const userPredicate = ow.object.exactShape({
22+
name: ow.string
23+
});
24+
25+
type User = Infer<typeof userPredicate>;
26+
```
27+
*/
28+
export type Infer<P> = P extends BasePredicate<infer T> ? T : never;
29+
1430
// Extends is only necessary for the generated documentation to be cleaner. The loaders below infer the correct type.
1531
export interface Ow extends Modifiers, Predicates {
1632
/**

test/types.ts

+87-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import test from 'ava';
22
import {ExpectTypeOf, expectTypeOf} from 'expect-type';
33
import {TypedArray} from 'type-fest';
4-
import ow, {BasePredicate} from '../source';
4+
import ow, {BasePredicate, Infer} from '../source';
55

66
test('type-level tests', t => {
77
t.is(typeof typeTests, 'function');
@@ -143,6 +143,92 @@ function typeTests(value: unknown): Array<(() => void)> {
143143
};
144144

145145
return tests;
146+
},
147+
148+
(): void => {
149+
const schema = ow.object.exactShape({
150+
undefined: ow.undefined,
151+
null: ow.null,
152+
nullOrUndefined: ow.nullOrUndefined,
153+
optionalString: ow.optional.string,
154+
number: ow.number,
155+
boolean: ow.boolean,
156+
symbol: ow.symbol,
157+
array: ow.array,
158+
function: ow.function,
159+
buffer: ow.buffer,
160+
object: ow.object,
161+
regExp: ow.regExp,
162+
date: ow.date,
163+
error: ow.error,
164+
promise: ow.promise,
165+
map: ow.map,
166+
set: ow.set,
167+
weakMap: ow.weakMap,
168+
weakSet: ow.weakSet,
169+
int8Array: ow.int8Array,
170+
uint8Array: ow.uint8Array,
171+
uint8ClampedArray: ow.uint8ClampedArray,
172+
int16Array: ow.int16Array,
173+
uint16Array: ow.uint16Array,
174+
int32Array: ow.int32Array,
175+
uint32Array: ow.uint32Array,
176+
float32Array: ow.float32Array,
177+
float64Array: ow.float64Array,
178+
arrayBuffer: ow.arrayBuffer,
179+
dataView: ow.dataView,
180+
sharedArrayBuffer: ow.sharedArrayBuffer,
181+
nan: ow.nan,
182+
iterable: ow.iterable,
183+
typedArray: ow.typedArray,
184+
nested: ow.object.exactShape({
185+
nested: ow.array.ofType(
186+
ow.object.exactShape({
187+
nested: ow.number
188+
})
189+
)
190+
})
191+
});
192+
193+
expectTypeOf<Infer<typeof schema>>().toEqualTypeOf<{
194+
undefined: undefined;
195+
null: null;
196+
nullOrUndefined: null | undefined;
197+
optionalString: string | undefined;
198+
number: number;
199+
boolean: boolean;
200+
symbol: symbol;
201+
array: unknown[];
202+
function: Function;
203+
buffer: Buffer;
204+
object: object;
205+
regExp: RegExp;
206+
date: Date;
207+
error: Error;
208+
promise: Promise<unknown>;
209+
map: Map<unknown, unknown>;
210+
set: Set<any>;
211+
weakMap: WeakMap<object, unknown>;
212+
weakSet: WeakSet<object>;
213+
int8Array: Int8Array;
214+
uint8Array: Uint8Array;
215+
uint8ClampedArray: Uint8ClampedArray;
216+
int16Array: Int16Array;
217+
uint16Array: Uint16Array;
218+
int32Array: Int32Array;
219+
uint32Array: Uint32Array;
220+
float32Array: Float32Array;
221+
float64Array: Float64Array;
222+
arrayBuffer: ArrayBuffer;
223+
dataView: DataView;
224+
sharedArrayBuffer: SharedArrayBuffer;
225+
nan: number;
226+
iterable: Iterable<unknown>;
227+
typedArray: TypedArray;
228+
nested: {
229+
nested: Array<{nested: number}>;
230+
};
231+
}>();
146232
}
147233
];
148234
}

0 commit comments

Comments
 (0)