Let's say I have an interface:
interface IUser { email: string; id: number; phone: string; };
Then I have a function that expects a subset (or complete match) of that type. Maybe it will pass an entire object, made it will just pass in {email: "[email protected]"}
. I want the type checker to allow for both.
Example:
function updateUser(user: IUser) { // Update a "subset" of user attributes: $http.put("/users/update", user); }
Does Typescript support this sort of behavior yet? I could find it very useful, particularly with paradigms like Redux.
To clarify, the goal is:
if
statements, which forfeit benefits of compile time type checking.UPDATE: Typescript has announced support for mapped types which should solve this problem once published.
any. ❌ Don't use any as a type unless you are in the process of migrating a JavaScript project to TypeScript. The compiler effectively treats any as “please turn off type checking for this thing”. It is similar to putting an @ts-ignore comment around every usage of the variable.
Interfaces are most recommended for defining new objects or methods or properties of an object where it will receive a specific component. Hence interface works better when using objects and method objects. Therefore it is our choice to choose between types or interface according to the program needs.
The any type allows us to assign literally “any” particular value to that variable, simulating what we know as plain JavaScript - where types can dynamically be assigned from different types, such as a String value becoming a Number. The Any type. When to use Any in TypeScript.
object (lowercase “o”) in TypeScript: non-primitive values In TypeScript, object is the type of all non-primitive values (primitive values are undefined , null , booleans, numbers, bigints, strings). With this type, we can't access any properties of a value.
It's worth noting that Partial<T>
, as suggested in the accepted answer, makes all fields optional, which is not necessarily what you need.
If you want to make some fields required (e.g. id
and email
), you need to combine it with Pick
:
type UserWithOptionalPhone = Pick<IUser, 'id' | 'email'> & Partial<IUser>
Some explanation:
What Pick
does is that it lets you specify a subset of the interface succinctly (without creating a whole new interface repeating the field types, as suggested by other answers), and then lets you use those, and only those fields.
function hello1(user: Pick<IUser, 'id' | 'email'>) { } hello1({email: '@', id: 1}); //OK hello1({email: '@'}); //Not OK, id missing hello1({email: '@', id: 1, phone: '123'}); //Not OK, phone not allowed
Now, this is not exactly what we need, as we want to allow, but not require phone. To do that, we "merge" the partial and the "picked" version of our type by creating an intersection type, which then will have id
and email
as required fields, and everything else as optional – exactly how we wanted it.
function hello2(user: Pick<IUser, 'id' | 'email'> & Partial<IUser>) { } hello2({email: '@', id: 1}); //OK hello2({email: '@', id: 1, phone: '123'}); //OK hello2({email: '@'}); //Not OK, id missing
Typescript now supports partial types.
The correct way to create a partial type is:
type PartialUser = Partial<IUser>;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With