如何在 Typescript 中使用 ramda mergeRight 并遵守接口定义

How to use ramda mergeRight in Typescript and respect interface definitions

我正在尝试制作对象的副本并使用 Rambda 的 mergeRight 函数更改属性。问题是它允许我合并接口定义中不存在的属性。

import {mergeRight} from "ramda";

export interface User {
    readonly userId: string
    readonly username: string
}

const user: User = {
    userId: "12345",
    username: "SomeUser"
}

//I want this to be a compile time error, because "something" is not a property of User interface
const updatedUser: User = mergeRight(user, {something: "3"})

有什么方法可以确保我正在合并的属性是 User 类型的一部分,而不必指定一个完整的新用户对象(从而破坏 mergeRight 的优势)?这将防止简单的拼写错误导致难以调试的运行时错误。

理想情况下,我希望 Typescript 在编译时检测到这一点

要过滤掉不属于用户的键,请使用 R.pick 从新对象中仅获取存在于 User 中的键。

这只会影响对象的根级别,不会影响更深层次的不匹配。

const { pick, keys, mergeDeepRight } = R

const user = {
  userId: "12345",
  username: "SomeUser"
}

const getUserKeys = pick(keys(user))

//I want this to be an error, because "something" is not a property of User interface
const updatedUser = mergeDeepRight(user, getUserKeys({
  something: "3"
}))

console.log(updatedUser)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

似乎只是将匿名对象转换为 User 会给出我想要的错误。这对我的用例来说已经足够了。

//This causes a compile time error
const updatedUser: User = mergeRight(user, {something: "3"} as User)

//This does not
const updatedUser2: User = mergeRight(user, {userId: "3"} as User)