类型变量的Typescript空对象


84

说我有:

type User = {
...
}

我想创建一个新的user但将其设置为空对象:

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

我该怎么做呢?我不希望变量为null


13
您想要user的类型是User | {}Partial<User>,或者需要重新定义User类型以允许使用空对象。目前,编译器正确地告诉您user不是User
jcalz

Answers:


173

注意事项

这是评论中值得注意的两个事项。

您希望用户的类型为User | {}Partial<User>,或者需要重新定义User类型以允许使用空对象。现在,编译器正确地告诉您该用户不是用户。–jcalz

我认为这不应该被认为是正确的答案,因为它创建了一个不一致的类型实例,从而破坏了TypeScript的整个目的。在此示例中,该属性Username未定义,而类型注释表示该属性不能未定义。–Ian Liu Rodrigues

回答

TypeScript设计目标之一“在正确性和生产率之间取得平衡”。如果这样做会有所帮助,请使用类型断言为类型化变量创建空对象。

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

const user01 = {} as User;
const user02 = <User>{};

user01.Email = "foo@bar.com";

这是一个适合您的示例

这是带有建议的类型断言。


9
谢谢!解决了!这应该标记为正确答案...
Kokodoko

3
我认为这不应该被认为是正确的答案,因为它创建了一个不一致的类型实例,从而破坏了TypeScript的整个目的。在此示例中,该属性Username未定义,而类型注释表示该属性不能未定义。
伊恩·刘·罗德里格斯

2
好点@IanLiuRodrigues。我给答案加了一些警告。
Shaun Luttin

1
@IanLiuRodrigues TypeScript的目标之一是在正确性和生产率之间取得平衡,因此可以说这破坏了TypeScript的整个目的有点极端。github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
Shaun Luttin

21

确实取决于您要执行的操作。类型是打字稿中的文档,因此您想要显示有关在创建类型时应如何使用此内容的意图。

选项1:如果用户在整个生命周期中可能拥有某些但不是全部属性

将所有属性设为可选

type User = {
  attr0?: number
  attr1?: string
}

选项2:如果包含Users的变量可能开始为null

type User = {
...
}
let u1: User = null;

但是,实际上,如果要点是在知道将要分配给它的对象之前声明User对象,则您可能希望不let u1:User进行任何分配就这样做。

选项3:您可能想要的

确实,打字稿的前提是要确保您符合在类型上概述的思维模型,以避免犯错误。如果要一一添加东西到对象,这是TypeScript试图使您不要这样做的习惯。

您更可能希望创建一些局部变量,然后在准备成为完整用户时将其分配给包含User的变量。这样一来,您就永远不会剩下部分格式的用户。那些事情太过分了。

let attr1: number = ...
let attr2: string = ...
let user1: User = {
  attr1: attr1,
  attr2: attr2
}

不知道这是他要做什么,但是我们可能正在谈论一个单独的参数UserAttributes或处理传入参数的东西。它可能不是可接受的用户对象,因此可以单独定义。
弗洛雷斯

这不应是公认的答案。请参阅以下Shaun Luttin的帖子。
thargenediad

1

您可以在打字稿中按以下方式进行操作

 const _params = {} as any;

 _params.name ='nazeh abel'

由于typescript的行为不像javascript,因此我们必须将类型设为任意类型,否则它将不允许您将属性动态分配给对象


0

如果您声明一个空的对象常量,然后再分配值,那么您可以认为这些值是可选的(可能存在或可能不存在),因此只需将它们键入带问号的可选内容即可:

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

0

请注意,使用const user = {} as UserType仅提供智能感知,但在运行时user为空对象,{}并且内部没有属性。这意味着user.Email将给予undefined而不是""

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

因此,使用classwithconstructor可以实际创建具有默认属性的对象。

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

您也可以使用interface代替type

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

...,其余代码保持不变。


实际上,您甚至可以跳过该constructor部分并按如下方式使用它:

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: ""}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.