自动跳过不属于TypeScript类型的属性 [英] Auto-skip properties not belonging to the type in TypeScript

查看:136
本文介绍了自动跳过不属于TypeScript类型的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下类型声明:

Let's say I have the following type declaration:

declare type Point2D = { x: number, y: number }

我从服务器获取一些数据并得到以下信息:

I fetch some data from the server and get the following:

const response = { x: 1.2, y: 3.4, foreign1: 'value', foreign2: 'value' }

是否可以自动忽略所有不属于我的类型的属性?像这样:

Is it possible to automatically ignore all properties that do not belong to my type? Like this:

const point: Point2D = response // Should skip all props except for 'x' and 'y'

重要的是响应可以有任意数量的外来属性,所以我不能使用对象解构休息算子。

The important thing is that the reponse can have any number of foreign properties, so I cannot use object destructuring with the rest operator.

推荐答案

类型在运行时不可用。

为了使DRY成为可能,可以使用辅助定义对象:

In order to make things DRY, helper definition object can be used:

const Point2DDefinition = { x: 1, y: 1 };
type Point2D = typeof Point2DDefinition;

const point: Point2D = Object.entries(response)
.filter(([k]) => Object.keys(Point2DDefinition).includes(k))
.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {} as Point2D);

因为定义对象依赖于推断类型,所以它具有某些限制,例如:不能使用交集或联合类型(值不能同时是数字和字符串)。

Because definition object relies on inferred type, it has certain limitations, e.g. intersection or union types cannot be used (a value cannot be a number and a string at the same time).

请注意,此代码不包含<$的检查c $ c> point 拥有 Point2D 的所有属性,所以从技术上讲它更像是点:Partial< Point2D> 。它也不会检查值是否与定义中的值相同。

Notice that this code doesn't contain checks that point has all properties from Point2D, so technically it's more like point: Partial<Point2D>. It also doesn't check that values have same types as in definition.

在运行时,可以另外提供两种检查以确保类型安全。

Both checks can be additionally provided for type safety at runtime.

或者, Point2D 可以转换为一个在构造中省略不必要属性的类。

Alternatively, Point2D can be converted to a class that takes care of omitting unnecessary properties on construction.

属性应明确列出:

class Point2D {
    x: number;
    y: number;

    constructor({ x, y }: Point2D) {
        this.x = x;
        this.y = y;
    }
}

可以选择将验证添加到类构造函数中以确保类型安全在运行时。

Validation can be optionally added to class constructor for type safety at runtime.

未明确列出属性的解决方法是将类与辅助定义对象组合以迭代对象属性。 声明合并可用于断言 Point2D 类具有中列出的所有属性Point2DDefinition

A workaround for not listing properties explicitly would to combine a class with helper definition object to iterate over object properties. Declaration merging can be used to assert that Point2D class has all properties that are listed in Point2DDefinition:

type TPoint2D = typeof Point2DDefinition;

interface Point2D extends TPoint2D {};
class Point2D {
    constructor(point: Point2D) {
        for (const k of Object.keys(Point2DDefinition)) {
            // runtime check for value types can also be added
            if (k in point) {
                this[k] = point[k];
            } else {
                throw new TypeError();
            }
        }
    }
}




重要的是响应可以包含任意数量的外来属性,因此我不能将对象解构与其余运算符一起使用。

The important thing is that the reponse can have any number of foreign properties, so I cannot use object destructuring with the rest operator.

对象解构导致WET但是类型安全(在编译时)代码,当然可以用于此目的,例如:

Object destructuring results in WET but type-safe (at compilation time) code and certainly can be used for this purpose, for example:

const point: Point2D = (({ x, y }) => ({ x, y }))(response as Point2D);

它不需要 ...休息属性因为它们应该被丢弃。

It doesn't need the ...rest of the properties because they are supposed to be discarded.

这篇关于自动跳过不属于TypeScript类型的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆