Typescript:将对象属性和嵌套对象属性的类型更改为一种类型

问题描述 投票:0回答:4

有这个例子:

interface Event {
  title:string;
  description:string;
  fromDate: Date;
  toDate: Date;
  location: {
    name: string;
    lat: number;
    long: number;
  }
}

使用类似于

PropertiesToString<Event>
的类型,我希望返回此类型:

{
  title:string;
  description:string;
  fromDate: string;
  toDate: string;
  location: {
    name: string;
    lat: string;
    long: string;
  }
}

问题是如何创建

PropertiesToString<T>
类型?

我已经成功创建了一些可以工作但不适用于嵌套对象的东西。如果我有一个嵌套对象,而不是将对象属性修改为字符串,而是将对象设置为字符串。

这是我的版本,不适用于嵌套对象,因为它不是更改

location properties to string
的类型,而是更改
location itself to string
的类型:

export type RequestBody<T> = {
  [P in keyof T]: string;
};
typescript typescript-typings typescript-generics type-safety
4个回答
6
投票

type

ToString
将给定类型转换为
string
PropertiesToString
迭代传递的类型的每个键,并使用
string
将其类型更改为
ToString
。您可以使用类型三元运算符在
ToString
中添加要处理的其他特殊情况。

interface Event1 {
    title: string;
    description: string;
    fromDate: Date;
    toDate: Date;
    location: {
        name: string;
        lat: number;
        long: number;
  }
}

type ToString<T> = T extends Date
    ? string
    : T extends object
    ? PropertiesToString<T>
    : string

type PropertiesToString<T> = {
    [K in keyof T]: ToString<T[K]>
}

type Generated = PropertiesToString<Event1>

type X = PropertiesToString<Event1['location']>

const x: Generated = {
    title: 'lorem',
    description: 'lorem',
    fromDate: 'lorem',
    toDate: 'lorem',
    location: {
        name: 'lorem',
        lat: 'lorem',
        long: 'lorem',
    }
}

游乐场


2
投票

你们其实很亲近。但是,您可能需要处理一些边缘情况。在 JS 中,很多东西都是对象,你可能不希望它们全部简单地变成字符串。所以你可能需要用更多的逻辑来增强它。但最简单的是

type RecursiveObject<T> = T extends Date ? never : T extends object ? T : never; 
export type StringValues<TModel> = {
    [Key in keyof TModel]: TModel[Key] extends RecursiveObject<TModel[Key]> ? StringValues<TModel[Key]> : string;
};

添加您需要在代码中处理的任何特殊情况(数组?其他包装类型?)。最终我们将在类型中得到“not”处理,这会简单得多。


0
投票

另一种方法可以是:

// Do not control Date type here
type RecursiveObject<T> = T extends Date? never : T extends object ? T : never;
// Change properties (nested, or not) OT (Old Type) to NT (New Type)
type ToNewType<T, NT> = { [K in keyof T]: NT };
type NestedTypeChange<T, OT, NT> = {
    [k in keyof T]: T[k] extends OT ? NT : T[k] extends RecursiveObject<T[k]> ? ToNewType<NestedTypeChange<T[k], OT, NT>, NT> : NT
}

0
投票

您可以简单地编写如下函数,而不是使用

PropertiesToString<Event>

const eventToString = (e: Event) => ({
  ...e,
  formDate: e.fromDate.toString(),
  toDate: e.toDate.toString(),
  location: {
    ...e.location,
    lat: String(e.location.lat),
    long: String(e.location.long)
  }
})

type EventStringed = ReturnType<typeof eventToString>

它有一些优点:

  • 比使用高级 TS 功能更简单。
  • 你有JS函数来转换事件。
  • 除了简单的字符串之外,您还可以更改对象属性类型。
© www.soinside.com 2019 - 2024. All rights reserved.