类型定义在TypeScript的对象文字

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

class className {
property: string;
};

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

我已经尝试了以下代码,但它不能编译:

var obj = {
property: string;
};

我得到以下错误:

名称“string”在当前作用域中不存在

是我做错了什么还是这是个bug?

557797 次浏览

如果你试图写一个类型注释,语法是:

var x: { property: string; } = { property: 'hello' };

如果你试图写一个对象文字,语法是:

var x = { property: 'hello' };

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

你很接近了,你只需要用:代替=。您可以使用对象类型文字(参见规范第3.5.3节)或接口。使用对象类型文字接近于你所拥有的:

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

但是你也可以使用接口

interface MyObjLayout {
property: string;
}


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

更新2019-05-15(可选的改进代码模式)

在使用const多年并受益于更多函数式代码之后,我建议在大多数情况下不要使用我最初的答案(本节下面的标题,即在构建对象时,将类型系统强制为特定类型,而不是让它推断类型,这通常表明某些事情是错误的)。

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

const id = getId();
const hasStarted = true;
...
const hasFinished = false;
...
return { hasStarted, hasFinished, id };
  • 这将正确地键入所有内容,而不需要显式键入。
  • 不需要重新键入字段名。
  • 从我的经验来看,这导致了最干净的代码。
  • 这允许编译器提供更多的状态验证(例如,如果你在多个位置返回,编译器将确保总是返回相同类型的对象——这鼓励你在每个位置声明整个返回值——给出该值的完全明确的意图)。

附加信息:可选字段2022-09-29

const id = getId();
const optionalField = getOptionalValue();
return {
id,
// This will always exist as a key in the object but it might be undefined
optionalField,
// This will only exist as a key in the object if it has a truthy value
...optionalField2 ? { optionalField } : {},
// This will only exist as a key in the object if it is not null or undefined
...optionalField2 != null ? { optionalField } : {},
};

除了2020-02-26

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

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

# EYZ0

然后使用这个模式,并允许类型系统保护你免受意外的null/undefined访问:




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
}
}

99%的情况下不要做以下事情:

更新2016-02-10 -处理TSX(谢谢@Josh)

对TSX使用as运算符。

var obj = {
property: null as string
};

一个更长的例子:

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

原来的答案

使用强制转换操作符可以简化此操作(通过将null强制转换为所需类型)。

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

一个更长的例子:

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

这比分成两部分(一部分声明类型,另一部分声明默认值)要好得多:

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

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

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

例如:

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

如果你试图在变性对象文字中添加类型,例如在函数的参数中,语法是:

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


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

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

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

然后你可以这样使用它:

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

一个额外的好处是,您可以根据需要在任意多个对象上多次重用该接口。

祝你好运。

在你的代码中:

var obj = {
myProp: string;
};

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

var string = 'A string';


var obj = {
property: string
};

然而,你想要的是对象文字的类型。这可以通过多种方式实现:

接口:

interface myObj {
property: string;
}


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

类型别名:

type myObjType = {
property: string
};


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

对象类型文字:

var obj: { property: string; } = { property: "Mystring" };
// 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());

你可以使用预定义的实用程序类型<强> # EYZ0 < / >强:

const obj: Record<string, string> = {
property: "value",
};

它允许为你的对象文字指定键:

type Keys = "prop1" | "prop2"


const obj: Record<Keys, string> = {
prop1: "Hello",
prop2: "Aloha",
something: "anything" // TS Error: Type '{ prop1: string; prop2: string; something: string; }' is not assignable to type 'Record<Keys, string>'.
//   Object literal may only specify known properties, and 'something' does not exist in type 'Record<Keys, string>'.
};

属性值的类型:

type Keys = "prop1" | "prop2"
type Value = "Hello" | "Aloha"


const obj1: Record<Keys, Value> = {
prop1: "Hello",
prop2: "Hey", // TS Error: Type '"Hey"' is not assignable to type 'Value'.
};

这是我在2021年用TypeScript 4.5做的事情:

const sm = {
reg: {} as ServiceWorkerRegistration,
quantum: null as number | null,
currentCacheName: '' as string, // superfluous
badSWTimer: 0 as number, // superfluous
}

这不仅仅是一个值转换,对于对象属性来说,它的工作原理与接口定义相同。

更新:我包含了两个多余的类型作为示例。也就是说,这些类型可以自动推断,因此不会产生编译器错误。

来源:# EYZ0

  1. 使用type关键字创建类型
type ObjType = {
property: string;
}

然后,您可以使用它来绑定您的对象,以只接受这种类型,如下所示。

const obj: ObjType = {
property: "TypeScript"
}

用DRY将对象文字转换为类型

只做:

const myObject = {
hello: 'how are you',
hey: 'i am fine thank you'
}
type myObjectType = keyof typeof MyObject

完成工作!

要小心了。这对一些人来说可能是显而易见的,但类型声明:

const foo: TypeName = {}

和使用as的类型不一样:

const foo = {} as TypeName

尽管有人建议把它用在其他答案上。

例子:

谢谢,类型安全!:

const foo: { [K in 'open' | 'closed']: string } = {}
// ERROR: TS2739: Type '{}' is missing the following properties from type '{ open: string; closed: string; }': open, closed

再见,类型安全!:

const foo = {} as { [K in 'open' | 'closed']: string }
// No error

只是扩展@RickLove的回复…

这很好,因为你只需要定义不能推断的类型:

const initialState = {
user: undefined as User | undefined,
userLoading: false
};

它被编译成下面的js代码:

const initialState = {
user: undefined,
userLoading: false
};

如果你需要把它提取成一个类型,你可以这样做:

export type InitState = typeof initialState;