Typescript 将所有日期从接口转换为字符串

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

是否可以将所有

Date
类型定义从我的界面转换为
string
,因为它在JSON stringify上自动转换为
string

interface Item {
   key: string;
   value: number;
   created: Date;
}

const item: Item = { key: 'abc', value: 1, created: Date() };

// convert to JSON
const itemJson = JSON.stringify(item);

// convert back itemJson to an object
const item2 = JSON.parse(itemJson);

// item2 is not of type `Item` as JSON.stringify convert Dates to strings
// so item2 is of type: { key: string; value: number; created: string; }

是否有一种功能可以将

Date
类型从我的界面转换为
string
?有点像
const item2: ToJSON<Item> = JSON.parse(itemJson);

注: 我不想将

item2.created
转换回 Date,但我想创建一个新的
interface
对应于从
item
item2
的转换。所以
item
不同于
item2
并且应该保持不同,因此我需要一个新的
item2
界面。当然,我可以手动完成,但我有一堆接口要转换,我想用类似于实用程序类型的东西来做这个:https://www.typescriptlang.org/docs/handbook/utility- types.html

注2: 目标是获得一个名为

Item2

的新界面
interface Item2 {
   key: string;
   value: number;
   created: string;
}

有点像

type Item2 = ToJSON<Item>
.

typescript typescript-typings
5个回答
11
投票

TypeScript 类型系统 FTW:

interface Item {
  key: string;
  value: number;
  created: Date;
}

type SwapDatesWithStrings<T> = {
  [k in keyof(T)]: (T[k] extends Date ? string : T[k]);
}

type JsonItems = SwapDatesWithStrings<Item>;

// JsonItems is the same as:
// interface JsonItems {
//   key: string;
//   value: number;
//   created: string;
// }

它可以从基本类型

SwapDatesWithStrings
派生出泛型类型
T
,具有与
T
相同的一组属性,但属性类型有所不同:从 Date 派生的属性被转换为字符串。


2
投票

在这种情况下,需要 2 种类型,除了单个字段的类型注释外,它们在其他方面是相同的。

解决方案:通用接口

使接口通用将允许您使用类型参数对其进行参数化,并在您的两种类型中重复使用它。有关更多信息,请参见TypeScript 泛型

将此应用于您的示例:

interface Item<T> {
    key: string;
    value: number;
    created: T;
}

const item: Item<Date> = { key: 'abc', value: 1, created: Date() };

// convert to JSON
const itemJson = JSON.stringify(item);

// convert back itemJson to an object
const item2: Item<string> = JSON.parse(itemJson);

0
投票

也许考虑将

Item
声明为一个类。 有许多库可以帮助将普通对象转换为类实例,例如类变压器


0
投票

好吧,看看这个真棒,我是从这篇文章中得到的How to handle ISO date strings in TypeScript?

所以他说你可以添加一个恢复的功能,所以让我们在这里将它应用到你的问题:

interface Item {
   key: string;
   value: number;
   created: Date | string;
}

const item: Item = { key: 'abc', value: 1, created: Date() };

// convert to JSON
const itemJson = JSON.stringify(item);

// convert back itemJson to an object
// The juice is here, what you do is add the function as a second argument
const item2 = JSON.parse(itemJson, (key: any, value: any) => {
    // and in here you do your extra stuff...

    return Date.parse(value) ? new Date(value): value;

});

#Edit:需要注意的是,接口不会进入 JS,它们会被删除,所以如果你想确认你的接口可能具有字符串类型,那么可以像这样定义你的接口:

interface Item {
   key: string;
   value: number;
   created: Date | string; // at least this way you are acknowledging a potential string type
}

0
投票

扩展@alberto-chiesa 的答案,我们可以让它转换对象嵌套部分中的日期,并且也允许可选值:

type NestedSwapDatesWithStrings<T> = {
    [k in keyof T]: T[k] extends Date | undefined
        ? string
        : T[k] extends object
        ? NestedSwapDatesWithStrings<T[k]>
        : T[k];
};

它本质上是递归地尝试将

Dates
转换为
strings

© www.soinside.com 2019 - 2024. All rights reserved.