简体   繁体   English

如何在 TypeScript 中指定类型化的对象文字?

[英]How can I specify a typed object literal in TypeScript?

Is there a way to make a typed object literal directly?有没有办法直接制作类型化的对象文字?

By directly I mean without having to assign it to a variable which is type annotated.直接我的意思是不必将它分配给类型注释的变量。

For example, I know I can do it like this:例如,我知道我可以这样做:

export interface BaseInfo { value: number; }

export interface MyInfo extends BaseInfo { name: string; }

function testA(): BaseInfo = {
   const result: MyInfo = { value: 1, name: 'Hey!' };
   return result;
}

I also can do it like this:我也可以这样做:

function testB(): BaseInfo = {
   return { value: 1, name: 'Hey!' };
}

But what I need is something like:但我需要的是这样的:

function testC(): BaseInfo = {
   return { value: 1, name: 'Hey!' }: MyInfo; // <--- doesn't work
}

Or like this:或者像这样:

function testD(): BaseInfo = {
   return MyInfo: { value: 1, name: 'Hey!' }; // <--- doesn't work
}

Intellisense for members of object literals is provided by the contextual type (see section 4.19 of the spec) of the expression.对象文字成员的智能感知由表达式的上下文类型(参见规范的第 4.19 节)提供。

You can acquire a contextual type in a variety of ways.您可以通过多种方式获取上下文类型。 Some of the most common places where a contextual type is applied are:应用上下文类型的一些最常见的地方是:

  • The initializer of a variable with a type annotation带有类型注释的变量的初始化器
  • The expression in a return statement in a function or getter with a return type annotation带有返回类型注释的函数或 getter 中的return语句中的表达式
  • The expression in a type assertion expression ( <T>expr )类型断言表达式 ( <T>expr ) 中的表达式

In your example, you can use a type assertion to force your object literal to have a contextual type:在您的示例中,您可以使用类型断言来强制您的对象文字具有上下文类型:

function testB() {
   return <IMyInfo>{ name: 'Hey!' };
}

Answer is to use the identity function:答案是使用身份功能:

function to<T>(value: T): T { return value; }
const instance = to<MyInfo>({
    value: 1,
    name: 'Hey!',
});

there should be no performance impact for an unnecessary call the to function, it should be optimized away by the JIT compiler对不必要to函数调用应该没有性能影响,它应该被 JIT 编译器优化掉

Remember that that interfaces follow duck typing: if an object looks like it matches the interface, it does match the interface.请记住,接口遵循鸭子类型:如果一个对象看起来与接口匹配,则它确实与接口匹配。

So所以

function testB(): IBaseInfo = {
   return { name: 'Hey!' };
}

is exactly the same as完全一样

function testA(): IBaseInfo = {
   var result: IMyInfo = { name: 'Hey!' };
   return result;
}

Either way, the returned object looks like an IMyInfo, so it is an IMyInfo.无论哪种方式,返回的对象看起来都像一个 IMyInfo,所以它是一个 IMyInfo。 Nothing that happens inside the function affects what interfaces it matches.函数内部发生的任何事情都不会影响它匹配的接口。

However, in your examples, the return value of the function is IBaseInfo, so the compiler and intellisense will assume that the object is just an IBaseInfo.但是,在您的示例中,函数的返回值是 IBaseInfo,因此编译器和智能感知将假定该对象只是一个 IBaseInfo。 if you want the caller of the function to know that the return value is an IMyInfo, you need to make the return value of the function IMyInfo:如果你想让函数的调用者知道返回值是一个IMyInfo,你需要使函数IMyInfo的返回值:

function testB(): IMyInfo = {
   return { name: 'Hey!' };
}

or using type inference, simply或者简单地使用类型推断

function testB() = {
   return { name: 'Hey!' };
}

To be really type-safe there are these ways:要真正做到类型安全,有以下方法:

Example interface:示例界面:

interface IFoo {
  firstName: string;
  lastName: string;
}

specify the function result type指定函数结果类型

function useResultType(): IFoo {
  return {
    firstName: 'mars'
    // compile error, when lastName is missing
    // , lastName: 'xx'
  };
}

return a constant返回一个常数

function resultVariable() {
  const result: IFoo = {
    firstName: 'mars'
    // compile error, when lastName is missing
    // , lastName: 'xx'
  };
  return result;
}

use a generic identity function (note: rxjs has an identity function)使用一个通用的标识函数(注意:rxjs 有一个标识函数)

function ident<T>(value: T): T {
  return value;
}
function identityFunction() {
  return ident<IFoo>({
    firstName: 'mars'
    // compile error, when lastName is missing
    // , lastName: 'xx'
  });
}

when you just use type assertions - the compiler will not show an error when you return any other type (eg in the examples, I "forgot" the lastName member)当您只使用类型断言时 - 当您返回任何其他类型时,编译器不会显示错误(例如,在示例中,我“忘记”了lastName成员)

function asCast() {
  return {
      firstName: 'mars'
    // NO error
  } as IFoo;
}

function cast() {
  return <IFoo>{
      firstName: 'mars'
    // NO error
  };
}

you can check the examples in the Typescript Playground您可以查看Typescript Playground中的示例

Your first and second examples fail, so yo can't do that.你的第一个和第二个例子都失败了,所以你不能这样做。 :) :)

Pretty sure you don't have to specify any types on your literal.很确定您不必在文字上指定任何类型。 As long as your literal meets the interface requirements, you're good.只要你的文字符合接口要求,你就很好。

interface IMyInfo { name: string; }
var asdf = {
   name: "test"
}

var qwer: IMyInfo = asdf;

If you want intellisense, you have to do something like:如果您想要智能感知,您必须执行以下操作:

在此处输入图像描述

Or maybe this is what you're looking for.或者也许这就是你要找的。 Intellisense works here, at least on the playground. Intellisense 在这里工作,至少在操场上。

在此处输入图像描述

Or maybe this.或者也许这个。 :) :)

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM