22

有没有办法直接制作类型化的对象文字?

直接我的意思是不必将它分配给类型注释的变量。

例如,我知道我可以这样做:

export interface BaseInfo { value: number; }

export interface MyInfo extends BaseInfo { name: string; }

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

我也可以这样做:

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

但我需要的是这样的:

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

或者像这样:

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

5 回答 5

21

对象文字成员的智能感知由表达式的上下文类型(参见规范的第 4.19 节)提供。

您可以通过多种方式获取上下文类型。应用上下文类型的一些最常见的地方是:

  • 带有类型注释的变量的初始化器
  • return带有返回类型注释的函数或 getter中的语句中的表达式
  • 类型断言表达式 ( <T>expr)中的表达式

在您的示例中,您可以使用类型断言来强制您的对象文字具有上下文类型:

function testB() {
   return <IMyInfo>{ name: 'Hey!' };
}
于 2013-10-18T18:51:14.477 回答
16

答案是使用身份功能:

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

to函数将被 JIT 编译器优化掉,因此调用函数不会影响性能

于 2016-06-25T14:51:08.440 回答
2

请记住,接口遵循鸭子类型:如果一个对象看起来与接口匹配,则它确实与接口匹配。

所以

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

完全一样

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

无论哪种方式,返回的对象看起来都像一个 IMyInfo,所以它是一个 IMyInfo。函数内部发生的任何事情都不会影响它匹配的接口。

但是,在您的示例中,函数的返回值是 IBaseInfo,因此编译器和智能感知将假定该对象只是一个 IBaseInfo。如果你想让函数的调用者知道返回值是一个IMyInfo,你需要使函数IMyInfo的返回值:

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

或者简单地使用类型推断

function testB() = {
   return { name: 'Hey!' };
}
于 2013-10-18T23:59:45.963 回答
2

要真正做到类型安全,有以下方法:

示例界面:

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

指定函数结果类型

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

返回一个常数

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

使用一个通用的标识函数(注意:rxjs 有一个标识函数)

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

当您只使用类型断言时- 当您返回任何其他类型时编译器不会显示错误(例如,在示例中,我“忘记”了该lastName成员)

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

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

您可以查看Typescript Playground中的示例

于 2018-10-25T12:34:47.560 回答
1

你的第一个和第二个例子都失败了,所以你不能这样做。:)

很确定您不必在文字上指定任何类型。只要你的文字符合接口要求,你就很好。

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

var qwer: IMyInfo = asdf;

如果您想要智能感知,您必须执行以下操作:

在此处输入图像描述

或者也许这就是你要找的。Intellisense 在这里工作,至少在操场上。

在此处输入图像描述

或者也许这个。:)

在此处输入图像描述

于 2013-10-18T18:00:42.290 回答