我遇到了这个打字挑战MyReadonly2.以下是我最初的解决方案:

// doesn't work as `Exclude` could potentially change the existing `readonly` modifier in the object 
type MyReadonly2<T, K extends keyof T = keyof T> =  { [P in Exclude<keyof T, K>]: T[P] } & { readonly [P in K]: T[P] }

以下是正确答案之一:

type MyReadonly2<T, K extends keyof T = keyof T> =  Omit<T, K> & { readonly [P in K]: T[P] }

这两种方法基本上有相同的 idea ,但我如何确保在复制对象成员时不会更改对象的只读修饰符?与Omit的唯一区别是对K:的类型约束:

type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }

为什么会有不同呢?

推荐答案

类型脚本中的keyof子句导致具有只读/可选元数据的中间类型

type X = keyof {a?: 1} // 'a' & {[optional]: true, [readonly]: false}

但是,任何类型的操作都会丢失此元数据

type X = keyof {a?: 1} & string // just 'a'
type X = Extract<keyof {a?: 1}, string> // just 'a'
type X = [keyof {a?: 1}] // just ['a']

so when you { [P in Exclude<keyof T, K>]: T[P] } you lose that metadata when you Exclude<keyof T, ...>
Use { [P in keyof T as P extends K ? never : P>]: T[P] } instead

所以...

type Omit2<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }

不是一个正确的实现(即使这是TS内置的shows),因为它损失了readonly.

https://tsplay.dev/N7z2qw

Typescript相关问答推荐

如何修复VueJS中的val类型不能赋给函数

如何在函数参数中使用(或模仿)`success`的行为?

如何使用泛型类型访问对象

react 路由6操作未订阅从react 挂钩表单提交+也不使用RTK查询Mutations

基于键的值的打字动态类型;种类;

在TypeScrip中分配回调时,参数的分配方向与回调本身相反.为什么会这样呢?

未在DIST中正确编译TypeScrip src模块导入

对未到达受保护路由的路由环境做出react

错误TS2403:后续变量声明必须具有相同的类型.变量';CRYPTO';的类型必须是';CRYPATO';,但这里的类型是';CRYPATO';

FatalError:Error TS6046:';--模块分辨率';选项的参数必须是:'; node ';,'; node 16';,'; node

转换器不需要的类型交集

正确使用相交类型的打字集

是否有可能避免此泛型函数体中的类型断言?

我可以使用typeof来强制执行某些字符串吗

缩小对象具有某一类型的任意字段的范围

如何在Type脚本中创建一个只接受两个对象之间具有相同值类型的键的接口?

TypeScript:如何使用泛型和子类型创建泛型默认函数?

是否使用类型将方法动态添加到类?

有没有一种简单的方法可以访问Keyboard Shortcuts JSON文件中列出的每个命令的显示名称(标题)?

为什么我的 Typescript 函数中缺少 void 隐式返回类型?