TypeScript 中对象字面量的类型定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12787781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 00:50:55  来源:igfitidea点击:

Type definition in object literal in TypeScript

typescript

提问by Dace Zarina

In TypeScript classes it's possible to declare types for properties, for example:

在 TypeScript 类中,可以为属性声明类型,例如:

class className {
  property: string;
};

How do declare the type of a property in an object literal?

如何在对象字面量中声明属性的类型?

I've tried the following code but it doesn't compile:

我尝试了以下代码,但无法编译:

var obj = {
  property: string;
};

I'm getting the following error:

我收到以下错误:

The name 'string' does not exist in the current scope

当前作用域中不存在名称“字符串”

Am I doing something wrong or is this a bug?

我做错了什么还是这是一个错误?

回答by Brian Terlson

You're pretty close, you just need to replace the =with a :. You can use an object type literal (see spec section 3.5.3) or an interface. Using an object type literal is close to what you have:

你很接近,你只需要更换=一个:。您可以使用对象类型文字(请参阅规范第 3.5.3 节)或接口。使用对象类型文字与您所拥有的很接近:

var obj: { property: string; } = { property: "foo" };

But you can also use an interface

但是你也可以使用接口

interface MyObjLayout {
    property: string;
}

var obj: MyObjLayout = { property: "foo" };

回答by Rick Love

Update 2019-05-15 (Improved Code Pattern as Alternative)

2019 年 5 月 15 日更新(改进的代码模式作为替代方案)

After many years of using constand benefiting from more functional code, I would recommend against using the below in most cases. (When building objects, forcing the type system into a specific type instead of letting it infer types is often an indication that something is wrong).

经过多年使用const更多功能代码并从中受益后,我建议在大多数情况下不要使用以下代码。(在构建对象时,将类型系统强制转换为特定类型而不是让它推断类型通常表明出现了问题)。

Instead I would recommend using constvariables as much as possible and then compose the object as the final step:

相反,我建议const尽可能多地使用变量,然后将对象作为最后一步:

const id = GetId();
const hasStarted = true;
...
const hasFinished = false;
...
return {hasStarted, hasFinished, id};
  • This will properly type everything without any need for explicit typing.
  • There is no need to retype the field names.
  • This leads to the cleanest code from my experience.
  • This allows the compiler to provide more state verification (for example, if you return in multiple locations, the compiler will ensure the same type of object is always returned - which encourages you to declare the whole return value at each position - giving a perfectly clear intention of that value).
  • 这将正确键入所有内容,而无需显式键入。
  • 无需重新键入字段名称。
  • 根据我的经验,这导致了最干净的代码。
  • 这允许编译器提供更多的状态验证(例如,如果您在多个位置返回,编译器将确保始终返回相同类型的对象 - 这鼓励您在每个位置声明整个返回值 - 给出一个非常清楚的该值的意图)。

Addition 2020-02-26

添加 2020-02-26

If you do actually need a type that you can be lazily initialized: Mark it is a nullable union type (null or Type). The type system will prevent you from using it without first ensuring it has a value.

如果您确实需要一个可以延迟初始化的类型:将其标记为可空联合类型(null 或 Type)。类型系统将阻止您在没有首先确保它具有值的情况下使用它。

In tsconfig.json, make sure you enable strict null checks:

在 中tsconfig.json,确保启用严格的空检查:

"strictNullChecks": true

"strictNullChecks": true

Then use this pattern and allow the type system to protect you from accidental null/undefined access:

然后使用此模式并允许类型系统保护您免受意外空/未定义访问:



const state = {
    instance: null as null | ApiService,
    // OR
    // instance: undefined as undefined | ApiService,

};

const useApi = () => {
    // If I try to use it here, the type system requires a safe way to access it

    // Simple lazy-initialization 
    const api = state?.instance ?? (state.instance = new ApiService());
    api.fun();

    // Also here are some ways to only access it if it has value:

    // The 'right' way: Typescript 3.7 required
    state.instance?.fun();

    // Or the old way: If you are stuck before Typescript 3.7
    state.instance && state.instance.fun();

    // Or the long winded way because the above just feels weird
    if (state.instance) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans way
    if (state.instance != null) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans 
    // AND I was told to always use triple === in javascript even with null checks way
    if (state.instance !== null && state.instance !== undefined) { state.instance.fun(); }
};

class ApiService {
    fun() {
        // Do something useful here
    }
}


Do not do the below in 99% of cases:

在 99% 的情况下不要执行以下操作:

Update 2016-02-10 - To Handle TSX (Thanks @Josh)

2016 年 2 月 10 日更新 - 处理 TSX(感谢 @Josh)

Use the asoperator for TSX.

使用asTSX的运算符。

var obj = {
    property: null as string
};

A longer example:

一个更长的例子:

var call = {
    hasStarted: null as boolean,
    hasFinished: null as boolean,
    id: null as number,
};

Original Answer

原答案

Use the cast operator to make this succinct (by casting null to the desired type).

使用强制转换运算符使其简洁(通过将 null 强制转换为所需类型)。

var obj = {
    property: <string> null
};

A longer example:

一个更长的例子:

var call = {
    hasStarted: <boolean> null,
    hasFinished: <boolean> null,
    id: <number> null,
};

This is much better than having two parts (one to declare types, the second to declare defaults):

这比有两个部分(一个声明类型,第二个声明默认值)要好得多:

var callVerbose: {
    hasStarted: boolean;
    hasFinished: boolean;
    id: number;
} = {
    hasStarted: null,
    hasFinished: null,
    id: null,
};

回答by LogicalBranch

I'm surprised that no-one's mentioned this but you could just create an interface called ObjectLiteral, that accepts key: valuepairs of type string: any:

我很惊讶没有人提到这一点,但您可以创建一个名为 的接口ObjectLiteral,该接口接受key: value类型对string: any

interface ObjectLiteral {
  [key: string]: any;
}

Then you'd use it, like this:

然后你会使用它,就像这样:

let data: ObjectLiteral = {
  hello: "world",
  goodbye: 1,
  // ...
};

An added bonus is that you can re-use this interface many times as you need, on as many objects you'd like.

一个额外的好处是,您可以根据需要在任意数量的对象上多次重复使用此界面。

Good luck.

祝你好运。

回答by Ryan Cavanaugh

If you're trying to write a type annotation, the syntax is:

如果您尝试编写类型注释,则语法为:

var x: { property: string; } = ...;

If you're trying to write an object literal, the syntax is:

如果你想写一个对象字面量,语法是:

var x = { property: 'hello' };

Your code is trying to use a type name in a value position.

您的代码试图在值位置使用类型名称。

回答by mukund patel

In TypeScript if we are declaring object then we'd use the following syntax:

在 TypeScript 中,如果我们声明对象,那么我们将使用以下语法:

[access modifier] variable name : { /* structure of object */ }

For example:

例如:

private Object:{ Key1: string, Key2: number }

回答by Egor

If you're trying to add typings to a destructuredobject literal, for example in arguments to a function, the syntax is:

如果您尝试将类型添加到解构的对象文字中,例如在函数的参数中,语法是:

function foo({ bar, baz }: { bar: boolean, baz: string }) {
  // ...
}

foo({ bar: true, baz: 'lorem ipsum' });

回答by Hamza Ibrahim

// Use ..

const Per = {
  name: 'HAMZA',
  age: 20,
  coords: {
    tele: '09',
    lan: '190'
  },
  setAge(age: Number): void {
    this.age = age;
  },
  getAge(): Number {
    return age;
  }
};
const { age, name }: { age: Number; name: String } = Per;
const {
  coords: { tele, lan }
}: { coords: { tele: String; lan: String } } = Per;

console.log(Per.getAge());

回答by streletss

If your properties have the same type, you could use predefined utility type Record:

如果您的属性具有相同的类型,则可以使用预定义的实用程序类型Record

type Keys = "property" | "property2"

var obj: Record<Keys, string> = {
  property: "my first prop",
  property2: "my second prop",
};

You can of course go further and define a custom type for your property values:

您当然可以更进一步,为您的属性值定义自定义类型:

type Keys = "property" | "property2"
type Value = "my prop" | "my other allowed prop"

var obj: Record<Keys, Value> = {
  property: "my prop",
  property2: "my second prop", // TS Error: Type '"my second prop"' is not assignable to type 'Value'.
};

回答by Willem van der Veen

In your code:

在您的代码中:

var obj = {
  myProp: string;
};

You are actually creating a object literal and assigning the variable string to the property myProp. Although very bad practice this would actually be valid TS code (don't use this!):

您实际上是在创建一个对象文字并将变量字符串分配给属性 myProp。尽管非常糟糕的做法,这实际上是有效的 TS 代码(不要使用它!):

var string = 'A string';

var obj = {
  property: string
};


However, what you want is that the object literal is typed. This can be achieved in various ways:

但是,您想要的是键入对象文字。这可以通过多种方式实现:

Interface:

界面:

interface myObj {
    property: string;
}

var obj: myObj = { property: "My string" };

Custom type:

自定义类型:

type myObjType = {
    property: string
};

var obj: myObjType = { property: "My string" };

Cast operator:

演员操作员:

var obj = {
    myString: <string> 'hi',
    myNumber: <number> 132,
};

Object type literal:

对象类型文字:

var obj: { property: string; } = { property: "Mystring" };