2

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"
1

3 Answers 3

1

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

TS Playground

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) */

TS Playground

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) */

TS Playground

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
}

TS Playground

Sign up to request clarification or add additional context in comments.

Comments

1

If you create a class that implements the interface you can set the default value of the properties to be empty

class Class implements Person {
  name: string = "";
  age: number = 0;
  city: string = "";
}

and then set them as you want later

Comments

0

One way around this is to declare an object with "empty" properties and then initialize them afterwards

export interface person {
  name: string;
  age: number;
  city: string;

}


let user2:person = {
    name:"",
    age:-1,
    city:""
};

user2.age = 22;
user2.name = "Dave";
user2.city = "NY"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.