我需要创建一个排除某些文字类型并接受所有其他字符串的类型。我试过这个:
type ExcludedKeys = "a"|"b"
type MyType = {
[K in Exclude<string,ExcludedKeys>]: any
}
const obj: MyType = {
a: 0, // No Error
b: 1 // No Error
}
Run Code Online (Sandbox Code Playgroud)
但很快我发现,这Exclude<string,ExcludedKeys>只是简单地评估string,并且不可能以这种方式做到这一点。然后我尝试了这种方法:
type ExcludedKeys = "a"|"b"
type MyType<T> = keyof T extends ExcludedKeys ? never : {
[K in keyof T]: T[K]
}
declare class Obj {
a: number
b: number
c: number // Adding this removes the wanted error.
}
const obj: MyType<Obj> = {
a: …Run Code Online (Sandbox Code Playgroud) 我只需要选择两个名称尚未从类型中定义的属性,然后从那里创建一个新类型,其中一个属性是必需的,另一个属性是可选的。
我知道可以选择一个单一的房产
<T extends Record<string,any>> {
[K in keyof T]: (Record<K, T[K]> &
Partial<Record<Exclude<keyof T, K>, never>>) extends infer U ? { [P in keyof U]: U[P] } : never
}[keyof T]
Run Code Online (Sandbox Code Playgroud)
但没有弄清楚如何(以及是否)可以使用此方法选择两个属性。
下面是我想如何使用它的示例
class Article {
name: string
id: number
content?: string
}
const article: TwoKeys<Article> = { id: 23 } // no error
const article: TwoKeys<Article> = { name: "my article", id: 122 } // no error
const article: TwoKeys<Article> = { name: "my article" , id: 23, …Run Code Online (Sandbox Code Playgroud) 在 javascript 中,我们可以使用点表示法向对象添加新属性
const obj = {}
obj.a = "hello"
console.log(obj) // prints { a: "hello" }
Run Code Online (Sandbox Code Playgroud)
但是,使用点表示法,无法将属性添加到尚不存在的对象
obj.a.b = "hello" // <-- cannot set properties of undefined (setting 'b')
obj.a = { b: "hello" } // <-- OK
Run Code Online (Sandbox Code Playgroud)
我想实现这种行为
const obj = {}
obj.a.b = "hello"
console.log(obj) // prints { a: { b: "hello" } }
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一可以接近这个的就是使用代理
const obj = new Proxy({}, {
set(target, key, receiver) {
// if a.b could make it here before the …Run Code Online (Sandbox Code Playgroud)