首页 > 解决方案 > 将 Typescript 泛型约束为对象

问题描述

嗨,大家好,

我对Typescript不太熟悉,但这是我想要实现的以下目标,我目前正在努力解决:

createObject使用如下定义的函数创建一个对象。作为参数,您只能传入Object类型的参数。

它返回传入的参数,但由 type 和 detail 属性修改)。

这就是我到目前为止所做的。

function createObject<T extends object>(options: T): T {
  if (!options.type) {
    if (options.showDetail) {
      options.type = 'text';
      options.detail = 'Some detail';
    } else {
      options.type = 'simple';
      options.detail = '';
    }
  }
  return options
}

当我执行我的功能时:

const objectConfig = {
  name: 'Steven',
  age: 28,
}

const newObj = createObject(objectConfig);

在函数内部createObjectoptions.type, options.showDetail, options.detail以红色突出显示。打字稿抱怨:

[第 4 行] 类型“T”上不存在属性“类型”。

[第 3 行] 类型“T”上不存在属性“showDetail”。

[第 5、8 行] 类型“T”上不存在属性“详细信息”。

此外,返回 Generic 不会返回修改后的参数,而只会返回输入参数。即我不会得到关于 .detail/type 属性的 Typescript 提示newObj

我的 IDE 只是给我年龄和名称属性的类型提示。正如预期的那样,因为我错误地返回了输入参数。

如何获得合适的打字稿解决方案?谢谢!

标签: javascripttypescript

解决方案


嗯...问题是您正在编写 TypeScript,就好像它就像 JavaScript 一样。这不是它的工作原理。这是一个可行的解决方案,您需要像编写任何其他 OOP 语言1一样开始编写 TypeScript 。

interface OptionExtensions {
    type?: string,
    showDetail?: boolean,
    detail?: string
}

function createObject<T extends object>(options: T): T & OptionExtensions {
    let optionsExtended: T & OptionExtensions = options;
    if (!optionsExtended.type) {
        if (optionsExtended.showDetail) {
            optionsExtended.type = 'text';
            optionsExtended.detail = 'Some detail';
        } else {
            optionsExtended.type = 'simple';
            optionsExtended.detail = '';
        }
    }
    return optionsExtended;
}

let foo = createObject({
    name: "Steven",
    age: 28
});

这是一个演示。您可以检查是否foo具有您期望的所有属性(通过编写“foo.”并查看建议)。

脚注 1:我的意思是因为 TypeScript 有很好的类型推断鸭式类型,它可以让你在不显式编写类型和制作接口的情况下让事情正常工作,但不会持续太久。想想你将如何用 OOP 语言编写东西,然后做出适当的抽象和模型。


推荐阅读