如果我们有一个界面(主要简化)

interface User {
       Id: number;
       Firstname: string;
       Lastname: string;
       Age: number;
       Type: string;
    }

我正在重构的当前逻辑以以下方式构建搜索字符串:

    function formatSearchCriteriaText(user: User): string {
       let searchText = "Date:" + Date.now();
       //currently calls out every single property.
       searchText += (user.Id) ? ", Id: " + user.Id : "";
       searchText += (user.Lastname) ? ", Lastname: " + user.Lastname : "";
       searchText += (user.Firstname) ? ", Firstname: " + user.Firstname : "";
       searchText += (user.Age) ? ", Age: " + user.Age : "";

       searchText += (user.Type) ? ", Type: " + user.Type : "";
       return searchText;
   }

如何最好地连接属性名称和值,以避免列出每个单独的属性.这是朝着正确方向迈出的一步吗?

type UserType<T> = {
      [P in keyof T]: T[P] ? `$,{P as string}: {T[P]}` : "";
    };

推荐答案

您不需要花费任何精力来编写像UserType<T>这样的类型,因为除了输出是string这一事实之外,您不需要任何文字脚本编译器来了解任何事情.所以我们就用string吧.

您可以重构formatSearchCriteriaText()的主体,通过在每个属性上进行映射来对每个属性执行相同的序列化逻辑.由于您关心顺序,因此需要在函数中至少指定mention个属性名称,即使只是指定该顺序也是如此.也许是这样的:

function formatSearchCriteriaText(user: User): string {
  const keys = ["Id", "Lastname", "Firstname", "Age", "Type"] as const;
  return "Date:" + Date.now() + 
    keys.map(k => user[k] ? ", " + k + ": " + user[k] : "").join("");
}

因此,keys是一个属性名称数组,我使用const assertion来要求类型脚本跟踪literal types个元素,因此它知道它们是"Id""LastName"等,而不仅仅是string.然后我们只用您的逻辑对该数组进行map()次运算,其中k是键,user[k]是值.TypeScrip允许user[k]的原因是因为它知道k是属性键之一,并且user[k]是有效的属性并且是类似stringnumber的可串行化类型.

您可以验证它是否正常工作:

const u: User = {
  Age: 10,
  Id: 0,
  Firstname: "John",
  Lastname: "Doe",
  Type: "Plumber or something"
};
console.log(formatSearchCriteriaText(u));
// "Date:1701657535878, Lastname: Doe, Firstname: John, Age: 10, Type: Plumber or something" 

如果顺序非常重要,那么您可以不提键,只按存储顺序迭代user的属性,例如使用the Object.entries() method:

function formatSearchCriteriaText(user: User): string {
  return "Date:" + Date.now() + 
    Object.entries(user).map(([k, v]) => v ? ", " + k + ": " + v : "").join("");
}
console.log(formatSearchCriteriaText(u));
// "Date:1701657535879, Age: 10, Firstname: John, Lastname: Doe, Type: Plumber or something" 

这甚至更简单,但是您可以看到属性没有按照您想要的顺序序列化.

Playground link to code

Typescript相关问答推荐

TypScript在对象上强制执行值类型时推断对象文字类型?

异步动态生成Playwright测试,显示未找到测试

为什么TypeScript假设文档对象始终可用?

具有动态键的泛型类型

未在DIST中正确编译TypeScrip src模块导入

从子类构造函数推断父类泛型类型

如何在深度嵌套的Reaction路由对象中隐藏父级?

`fetcher.load`是否等同于Get Submit?

通过泛型函数本身推断受约束的泛型参数的类型脚本问题

有没有办法防止类型交集绕过联合类型限制?

TYPE FOR ARRAY,其中每个泛型元素是单独的键类型对,然后在该数组上循环

如果判断空值,则基本类型Gaurd不起作用

如何从上传文件中删除预览文件图标?

如何键入对象转换器

Select 类型的子项

如何在TypeScript中将元组与泛型一起使用?

如何向我的自定义样式组件声明 custom.d.ts ?

React HashRouter,单击导航栏时页面重新加载出现问题

为什么我的 Typescript 函数中缺少 void 隐式返回类型?

根据索引将元组拆分为两个块