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

Javascript 自动跳过不属于TypeScript中类型的属性,javascript,typescript,Javascript,Typescript,假设我有以下类型声明: declare type Point2D = { x: number, y: number } 我从服务器获取一些数据,并获得以下信息: const response = { x: 1.2, y: 3.4, foreign1: 'value', foreign2: 'value' } 是否可以自动忽略所有不属于我的类型的属性?像这样: const point: Point2D = response // Should skip all props except for

假设我有以下类型声明:

declare type Point2D = { x: number, y: number }
我从服务器获取一些数据,并获得以下信息:

const response = { x: 1.2, y: 3.4, foreign1: 'value', foreign2: 'value' }
是否可以自动忽略所有不属于我的类型的属性?像这样:

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

重要的是,响应可以有任意数量的外部属性,因此我不能使用rest操作符进行对象分解。

类型在运行时不可用

为了使事物干燥,可以使用辅助对象定义对象:

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);
因为定义对象依赖于推断类型,所以它有一定的限制,例如不能使用交集或并集类型(值不能同时是数字和字符串)

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

这两种检查都可以在运行时额外提供类型安全性

或者,
Point2D
可以转换为一个类,该类负责在构造时忽略不必要的属性

属性应明确列出:

class Point2D {
    x: number;
    y: number;

    constructor({ x, y }: Point2D) {
        this.x = x;
        this.y = y;
    }
}
可以选择将验证添加到类构造函数中,以在运行时实现类型安全

不显式列出属性的解决方法是将类与帮助器定义对象结合起来,以迭代对象属性。可用于断言
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();
            }
        }
    }
}
重要的是,响应可以有任意数量的外部属性,因此我不能使用rest操作符进行对象分解

对象分解会产生湿的但类型安全的代码(在编译时),当然可以用于此目的,例如:

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

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

如果你已经知道你想要的属性,为什么你必须使用rest操作符?简单回答,不。你在运行时没有关于类型的信息,因此你不能基于它的属性创建一个新对象。