Skip to content

Commit

Permalink
fix: add generic type to parse (#133)
Browse files Browse the repository at this point in the history
Given the following code:
```ts
/**
 * Removes `null`, `undefined` and `?` from an object
 * This essentially combines `Required<T>`,
 * `NonNullable<T>` and `NonUndefined<T>`
 */
type NonNullish<T> = {
	[P in keyof T]-?: Exclude<T[P], undefined | null>;
};

/**
 * Type union for the full 2 billion dollar mistake in the JavaScript ecosystem
 */
type Nullish = null | undefined;

interface MyArgs {
	offset: number | Nullish;
	take: number | Nullish;
}

/**
 * Validate the schema
 *
 * Note: After calling `parse` the values will never be
 * `null` or `undefined` because of the nullish coalescing.
 */
const schema: SchemaOf<MyArgs> = s.object({
	offset: s.number.greaterThanOrEqual(0).nullish.transform((v) => v ?? 0),
	take: s.number
		.greaterThanOrEqual(1)
		.lessThanOrEqual(50)
		.nullish.transform((v) => v ?? 1),
});

/**
 * Validates and transforms the args
 */
function validate(args: MyArgs): NonNullish<MyArgs> {
	return schema.parse(args);
}
```
This would previously give an error on `validate`:
```ts
Type 'MyArgs' is not assignable to type
'NonNullish<MyArgs>'.
	Types of property 'offset' are incompatible.
		Type 'number | Nullish' is not assignable to type 'number'.
			Type 'undefined' is not assignable to type 'number'.
ts(2322)
```
  • Loading branch information
favna authored Jun 22, 2022
1 parent b9988e7 commit 90c91aa
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/validators/BaseValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ export abstract class BaseValidator<T> {
return result;
}

public parse(value: unknown): T {
public parse<R extends T = T>(value: unknown): R {
// If validation is disabled (at the validator or global level), we only run the `handle` method, which will do some basic checks
// (like that the input is a string for a string validator)
if (!this.shouldRunConstraints) {
return this.handle(value).unwrap();
return this.handle(value).unwrap() as R;
}

return this.constraints.reduce((v, constraint) => constraint.run(v).unwrap(), this.handle(value).unwrap());
return this.constraints.reduce((v, constraint) => constraint.run(v).unwrap(), this.handle(value).unwrap()) as R;
}

/**
Expand Down

0 comments on commit 90c91aa

Please sign in to comment.