Issue
I have an Interface Person
and I am able to create an object user1
of the type Person
by assigning all the properties at once
export interface person {
name: string;
age: number;
city: string;
}
let user1: person = {
name:"ron",
age: 22,
city:"AL"
}
Is there a way for me to build this object instead of assigning all the properties at once. Im am looking for something like this
let user2:person;
user2.age = 22;
user2.name = "Dave";
user2.city = "NY"
Solution
You can use the type utility Partial<Type>
when initializing the value to indicate that the properties have not yet been defined:
let user: Partial<Person> = {};
After initializing the property values, TypeScript will correctly infer that they do indeed exist:
user.age = 22;
user.name = "Dave";
user.city = "NY";
const doubleAge = user.age * 2; // Ok
const lowercaseCity = user.city.toLowerCase(); // Ok
const uppercaseName = user.name.toUpperCase(); // Ok
However, if you do not initialize one of the property values, TypeScript will emit an error diagnostic when trying to use it:
let user: Partial<Person> = {};
user.age = 22;
const doubleAge = user.age * 2; // Ok
const lowercaseCity = user.city.toLowerCase(); /* Error
~~~~~~~~~
'user.city' is possibly 'undefined'.(18048) */
const uppercaseName = user.name.toUpperCase(); /* Error
~~~~~~~~~
'user.name' is possibly 'undefined'.(18048) */
There are still some scenarios where the inference isn't enough — for example, when the value needs to be used as an argument to a function which requires a Person
:
declare function doSomethingWithPerson(person: Person): void;
let user: Partial<Person> = {};
user.age = 22;
user.name = "Dave";
user.city = "NY";
doSomethingWithPerson(user); /* Error
~~~~
Argument of type 'Partial<Person>' is not assignable to parameter of type 'Person'.
Property 'name' is optional in type 'Partial<Person>' but required in type 'Person'.(2345) */
In these cases, you can create a function called a type guard which will check at runtime to ensure that the type meets the stated expectations. A user-defined type guard is a function whose return type is a type predicate:
function isPerson<T extends Record<PropertyKey, unknown>>(
p: T,
): p is T & Person {
return (
typeof p.age === "number" &&
typeof p.city === "string" &&
typeof p.name === "string"
);
}
See also in the handbook: generics
Then you can check whether user
actually meets the definition of Person
before using it in order to avoid errors:
let user: Partial<Person> = {};
user.age = 22;
user.name = "Dave";
user.city = "NY";
if (isPerson(user)) {
doSomethingWithPerson(user); // Ok
} else {
// Handle the other case here
}
Answered By - jsejcksn
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.