How to start an object in Typescript without declaring all properties at once?

Asked

Viewed 588 times

3

Taking into account the following interface:

interface Usuario {
    nome: string;
    senha: string;
    email: string;
}

It is possible to declare an object "slowly" without creating a new type or interface with all properties being optional (?)? If yes, how? Example:

function criarUsuario(nome: string, senha: string, email: string): Usuario {
    const usuario: Usuario = {}; // Aqui ocorre um erro porque o objeto ainda está vazio
    // ...
    usuario.nome = nome;
    usuario.senha = senha;
    usuario.email = email;
    return usuario;
}

The example is simplified, I know that in this situation it makes no sense to define property by property.

1 answer

4


You can use the built-in type Partial<T>, which makes all properties of type T optional:

interface Usuario {
    nome: string;
    senha: string;
    email: string;
}

function criarUsuario(nome: string, senha: string, email: string): Usuario {
    const usuario: Partial<Usuario> = {};

    usuario.nome = nome;
    usuario.senha = senha;

    // Note que, embora `usuario.email` não tenha sido fornecido,
    // nenhum aviso ou erro é emitido pelo compilador.
    return usuario as Usuario;
}

See on Typescript playground.

The problem is that with this you will need to make a return assertion to tell the compiler that the object you are returning is actually a "full" user. Otherwise, Typescript will complain saying that Partial<Usuario> is not attributable to Usuario.

Note that in the above example I omitted the email and yet the compiler does not issue errors. Therefore, you are giving up "security" on a certain level. I personally don’t consider it good and I always try to avoid.

Another way to solve this is simply to use the type assertion logo in the statement (assignment to the empty object). However, this also does not solve the problem of unsafe types, as you can check in the code below:

interface Usuario {
    nome: string;
    senha: string;
    email: string;
}

function criarUsuario(nome: string, senha: string, email: string): Usuario {
    const usuario = {} as Usuario;
    usuario.nome = nome;
    usuario.senha = senha;
    // Note que também nenhum erro foi emitido.
    return usuario;
}

See on Typescript playground.

What to do then?

In your example, you could simply add all the properties during the literal initialization of the object. To ensure the "security" that I’ve talked about, this is the best way.

interface Usuario {
    nome: string;
    senha: string;
    email: string;
}

function criarUsuario(nome: string, senha: string, email: string): Usuario {
    const usuario: Usuario = {
        nome,
        senha,
        email
    };

    return usuario;
}

See on Typescript playground.

In the vast majority of cases it is possible to use this approach.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.