TypeScript empty object for a typed variable

Viewed 240885

Say I have:

type User = {
  ...
}

I want to create a new user but set it to be an empty object:

const user: User = {}; // This fails saying property XX is missing
const user: User = {} as any; // This works but I don't want to use any

How do I do this? I don't want the variable to be null.

9 Answers

An empty object can be written as Record<string,never>, so effectively your type for user is either an empty object or a User

const user : User | Record<string, never> = {};

Note that using const user = {} as UserType just provides intellisense but at runtime user is empty object {} and has no property inside. that means user.Email will give undefined instead of ""

type UserType = {
    Username: string;
    Email: string;
}

So, use class with constructor for actually creating objects with default properties.

type UserType = {
  Username: string;
  Email: string;
};

class User implements UserType {
  constructor() {
    this.Username = "";
    this.Email = "";
  }

  Username: string;
  Email: string;
}

const myUser = new User();
console.log(myUser); // output: {Username: "", Email: ""}
console.log("val: "+myUser.Email); // output: ""

You can also use interface instead of type

interface UserType {
  Username: string;
  Email: string;
};

...and rest of code remains same.


Actually, you can even skip the constructor part and use it like this:

class User implements UserType {
      Username = ""; // will be added to new obj
      Email: string; // will not be added
}

const myUser = new User();
console.log(myUser); // output: {Username: ""}

In my case Record<string, never> helps, it was recommended by eslint Eslint recommendations

you can do this as below in typescript

 const _params = {} as any;

 _params.name ='nazeh abel'

since typescript does not behave like javascript so we have to make the type as any otherwise it won't allow you to assign property dynamically to an object

user: USER

this.user = ({} as USER)

If you declare an empty object literal and then assign values later on, then you can consider those values optional (may or may not be there), so just type them as optional with a question mark:

type User = {
    Username?: string;
    Email?: string;
}

What i wanted is intellisense help for a chain of middlewares. Record<string, never> worked for me.

type CtxInitialT = Record<string, never>;
type Ctx1T = CtxInitialT & {
  name: string;
};
type Ctx2T = Ctx1T & {
  token: string;
};

cont ctx: CtxInitialT = {};
// ctx.name = ''; // intellisense error Type 'string' is not assignable to type 'never'
cont ctx1: Ctx1T = middleware1AugmentCtx(ctx);
// ctx1.name = 'ddd'; // ok
// ctx1.name1 = ''; // intellisense error Type 'string' is not assignable to type 'never'
cont ctx2: Ctx2T = middleware2AugmentCtx(ctx1);
// ctx2.token = 'ttt'; // ok
// ctx2.name1 = ''; // intellisense error Type 'string' is not assignable to type 'never'
Related