javascript - 如何从包含数据和委托(delegate)(TypeScript)的接口(interface)创建对象?

标签 javascript typescript

我理解了以下内容,

interface Teacher {
  id: number;
  name: string;
}

interface Func {
  (x: number, y: number): number;
}

const teacher: Teacher = {
  id: 1,
  name: "Aaron",
};
const add: Func = (x, y) => x + y;

但我不知道如何从以下接口(interface)创建对象?

interface TeacherFunc {
  id: number;
  name: string;
  (x: number, y: number): number;
}



// It is incomplete.
const tf: TeacherFunc = {
  id: 1,
  name: "Aaron",
};

最佳答案

JavaScript 中的每个函数都是一个对象(特别是 a Function object ),但您不能使用 object literal notation创建一个函数对象。如果您想创建一个带有附加属性的函数对象,则需要创建一个函数,然后向其添加属性,可以单独设置它们,也可以通过类似 Object.assign() 一次性添加所有属性。 .

首先让我们稍微改变一下TeacherFunc的定义:

interface TeacherFunc {
  id: number;
  teacherName: string;  // <-- changed name to teacherName
  (x: number, y: number): number;
}

我决定使用名为 teacherName 的属性,而不是 name,原因我稍后会解释。

无论如何,您可以使用 Object.assign() 创建一个 TeacherFunc,它将属性从其后续参数复制到其第一个参数:

const tf: TeacherFunc = Object.assign(
  (x: number, y: number) => x + y,
  {
    teacherName: "Aaron",
    id: 1,
  }
);

或者您可以先将其设为函数,然后再单独添加属性,由于 TypeScript 3.1 中添加了对 property declarations on functions 的支持,编译器将接受它。 :

const tf2: TeacherFunc = (x, y) => x + y;
tf2.teacherName = "Aaron";
tf2.id = 1;

如果您使用的是 teacherName 而不是 name,那么您就会这样做。


但是你有这个:

interface TeacherFunc {
  id: number;
  name: string; // <-- back to name
  (x: number, y: number): number;
}

带有name的版本很棘手而且很奇怪,因为all functions have a read-only name property 。因此,您只需将其设为函数即可免费获得 name 属性,但您无法通过赋值来更改它。如果您希望该名称为 "Aaron",您可以尝试将函数本身命名为 Aaron,至少在没有缩小器或其他 JS 转换的情况下,它可以以这种方式工作。或者您可以使用Object.defineProperty()设置它。

所以它可能看起来像这样:

const tf: TeacherFunc = Object.assign(
  function Aaron(x: number, y: number) { return x + y },
  {
    id: 1,
  }
);
console.log(tf.name); // "Aaron" hopefully

或者这个:

const Aaron: TeacherFunc = (x, y) => x + y;
Aaron.id = 1;
const tf2 = Aaron;
console.log(tf2.name); // "Aaron" hopefully

或者这个:

const tf3: TeacherFunc = (x, y) => x + y;
tf3.id = 1;
Object.defineProperty(tf3, "name", { value: "Aaron" });
console.log(tf3.name); // "Aaron" hopefully

但实际上,我会远离任何既可调用又具有非readonly name属性的接口(interface),因为它可以让你做实际的事情JavaScript 函数将拒绝:

tf3.name = "oops" // no compiler error, but
// 💥 ERROR at runtime: "name" is read-only

所以我会坚持使用teacherName之类的。

Playground link to code

关于javascript - 如何从包含数据和委托(delegate)(TypeScript)的接口(interface)创建对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69051792/

相关文章:

angular - 生成指定属性允许值的 Angular/TypeScript 类

javascript - React 如何解析数据

javascript - 在 ES6 类中声明静态常量?

javascript - Dojo 如何捕获用户对 Dojo.FilteringSelect 的 onkeyup 事件输入

函数参数的 typescript 通用约束

angular - 奇怪的 typescript/angular2 导入行为

Typescript - 错误地推断 'never'

javascript - 当应用程序在 Windows 上全屏显示时隐藏窗口菜单?

javascript - 如何避免 Angular 服务中的重复方法

javascript - 通过选择器更改 View 标签的字体