Description
TypeScript Version: 2.7.0-dev.201xxxxx
Feature request
It would be helpful when using strictNullChecks
to have some way to map a type with optional fields to an equivalent type with non-nullable fields. I would expect using the !
non-null assertion like syntax somewhere in a map type:
[P in K]: User[P]!;
// or
[P in K]!: User[P];
Why I want this
I've found that after turning on strictNullChecks
I run into a lot of data types that have optional fields (in particular return values from http requests where all fields could be missing) that end up producing a lot of false flag "possibly null" errors in down-stream code. The problem is that even though I validate data at a high level, the data type holds onto the "possibly undefined" type wherever the data type is used in down-stream code, for example in my React component tree props. The truth is many of these components only get rendered when those fields are populated, but TS doesn't know this and probably couldn't possibly know this.
So the obvious solution is to create mirrors of the original data types that have certain fields defined as non-null... but this becomes quite cumbersome and leaky to maintain, especially since you rightfully can't assign something that has an optional field to something that doesn't.
In the end what I'm really trying to express is a type derived from a type with null | undefined
removed from certain (or all) fields. Basically the opposite of Partial<>
. And if I can do this generically I can eliminate a lot of the maintenance cost.
Code
// Example of a source type where anything could be undefined
// (I encounter this a lot with swagger generated DTO types)
interface User {
id?: string;
name?: string;
}
// User with all fields made non-null
type CompleteUser {
[P in keyof User]: User[P]!;
// or
[P in keyof User]!: User[P];
}
// Example
function isCompleteUser(user: User): user is CompleteUser {
return user.id != null && user.name != null;
}
// Generic wrapper version
type Complete<T, K extends keyof T> = {
[P in K]: T[P]!;
// or
[P in K]!: T[P];
}
// Example with generic validator type guard function
function isComplete<T, K extends keyof T>(obj: T, ...keys: K[]): obj is Complete<T, K> {
return keys.every(key => obj[key] != null);
}
declare const user: User;
if (isComplete(user, "id", "name")) {
// user = { id: string; name: string; }
}