自动跳过不属于TypeScript类型的属性

Qoo*_*ooS 3 javascript typescript

假设我有以下类型声明:

declare type Point2D = { x: number, y: number }
Run Code Online (Sandbox Code Playgroud)

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

const response = { x: 1.2, y: 3.4, foreign1: 'value', foreign2: 'value' }
Run Code Online (Sandbox Code Playgroud)

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

const point: Point2D = response // Should skip all props except for 'x' and 'y'
Run Code Online (Sandbox Code Playgroud)

重要的是响应可以有任意数量的外来属性,所以我不能使用其余运算符的对象解构.

Est*_*ask 5

类型在运行时不可用.

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

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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

应明确列出属性:

class Point2D {
    x: number;
    y: number;

    constructor({ x, y }: Point2D) {
        this.x = x;
        this.y = y;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

不显式列出属性的解决方法是将类与辅助定义对象组合以迭代对象属性.声明合并可用于断言Point2D该类具有列出的所有属性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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

重要的是响应可以有任意数量的外来属性,所以我不能使用其余运算符的对象解构.

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

const point: Point2D = (({ x, y }) => ({ x, y }))(response as Point2D);
Run Code Online (Sandbox Code Playgroud)

它不需要...rest属性,因为它们应该被丢弃.