Is it possible to create an "empty" object from a TypeScript interface?

Viewed 5051

Suppose you have a very large object defined as a TypeScript interface:

interface AccountInterface {
  accountIdentifier?: string;
  sid?: string;
  idToken?: {
    aio?: string;
  };
  idTokenClaims?: {
      aio?: string;
  };
}

I would like the object to always have its properties and sub properties. They can either be a string or an empty string:

let account = {
  accountIdentifier: "",
  sid: "",
  idToken: {
    aio: "",
  },
  idTokenClaims: {
    aio: "",
  },
};

Reading the other questions I thought it would have been possible to do this:

const emptyAccount = {} as AccountInterface

console.log('emptyAccount ', emptyAccount)
console.log('emptyAccount.sid ', emptyAccount.sid)

But this doesn't create an object with all the properties as empty strings as desired.

It would be great if something like this would be possible, so there's no need to duplicate the object in the code, as in one for the interface and one for the object with empty string properties.

2 Answers

You can create a class that implements that interface, adding the default values, and use that to create your objects. You are still re-writing the same structure elsewhere, but now you only have to do it one time, and you could use the constructor to initialize your object with different values if you want.

interface AccountInterface {
  accountIdentifier?: string;
  sid?: string;
  idToken?: {
      aio?: string;
  };
  idTokenClaims?: {
      aio?: string;
  };
}

class Account implements AccountInterface {
  accountIdentifier = '';
  sid = '';
  idToken = { aio: '' };
  idTokenClaims = { aio: '' };
}

const emptyAccount = new Account();

Also, as pointed out by @apokryfos, you can also use the class to type objects, so there's no need to define both an instance and a class unless you are going to have objects implementing that instance that haven't been created using the class (as those would not have the methods defined in the class).

If you want to avoid using class and use a function to do something similar, you totally can:

function createAccount(): AccountInterface {
  return {
    accountIdentifier = '';
    sid = '';
    idToken = { aio: '' };
    idTokenClaims = { aio: '' };
  };
}

const emptyAccount = createAccount();

const emptyAccount = {} as AccountInterface should create an object. But your AccountInterface only includes properties which may exist but must not (because of the ?). So an empty object completely matches your AccountInterface.

If you want to have a property with a default value to be included then you will have to declare it in your interface.

interface AccountInterface {
    accountIdentifier: string|null // <- will be included in {} as AccountInterface
    sid?: string // <- will not be included in {} as AccountInterface
}
Related