是否有可能有一个条件类型可以测试可以为空的对象?
例如:
function test<T>(a: T): T extends {} ? string : never {
return null
}
let o1: {}
let o2: { fox? }
let o3: { fox }
test(o1)
test(o2)
test(o3) // this one should be 'never'
Run Code Online (Sandbox Code Playgroud)
由于条件类型测试也适用于继承,因此所有 3 种情况都会产生“字符串”,但如果至少需要该类型的一个属性(例如非空对象类型o3) ,我想产生“从不”
更新
当我写这个问题时,我试图找出我遇到的问题的原因。我认为我应该解决我的疑问而不是我的问题,并简化我的问题。然而答案偏离了我的问题。
基本上我试图构建一个函数,其中第一个参数是一个对象,如果第一个参数可以完全部分(用 {} 初始化),则第二个参数是可选的
function test<T extends {}>(a: T, ...x: T extends {} ? [never?] : [any])
function test(a, b) {
return null
}
let o1: {}
let o2: { fox? }
let o3: { fox }
test(o1) // ok
test(o2) // ok
test(o3) // should fail and require second argument
Run Code Online (Sandbox Code Playgroud)
您可以通过操作员以相对简单的方式完成此操作keyof。
请记住,这never本质上相当于空集
type Foo = keyof {} // never
type Bar = keyof { a: 1, b: 2 } // "a" | "b"
Run Code Online (Sandbox Code Playgroud)
应用于您的用例,这将变为
declare function f<T>(t: T): keyof T extends never ? string : never
const a = f({}) //string
const b = f({ a: 1 }) //never
Run Code Online (Sandbox Code Playgroud)
编辑
我不确定我是否完全理解您现在包含在问题中的用例,但如果想法是像对待空对象一样仅使用可选对象来处理对象,则可以使用更多类型的机制来实现。
OptionalPropertyOf让我们借用这个问题的定义。
给定一个类型T为Textends的对象object,我们可以定义以下内容
type OptionalPropertyOf<T extends object> = Exclude<{
[K in keyof T]: T extends Record<K, T[K]>
? never
: K
}[keyof T], undefined>
type ExcludeOptionalPropertyOf<T extends object> = Omit<T, OptionalPropertyOf<T>>
type Foo = { a: number, b: string }
type OptFoo = OptionalPropertyOf<Foo> // never
type NonOptFoo = ExcludeOptionalPropertyOf<Foo> // { a: number, b: string }
type Bar = { a: number, b?: string }
type OptBar = OptionalPropertyOf<Bar> // "b"
type NonOptBar = ExcludeOptionalPropertyOf<Bar> // { a: number }
type Baz = { a?: number, b?: string }
type OptBaz = OptionalPropertyOf<Baz> // "a" | "b"
type NonOptBaz = ExcludeOptionalPropertyOf<Baz> // {}
Run Code Online (Sandbox Code Playgroud)
f然后,我们稍微改变一下to的定义
declare function f<T extends object>(t: T): keyof ExcludeOptionalPropertyOf<T> extends never ? string : never
Run Code Online (Sandbox Code Playgroud)
现在你得到了你想要的东西
declare const a: Foo
declare const b: Bar
declare const c: Baz
declare const d: {}
const fa = f(a) // never
const fb = f(b) // never
const fc = f(c) // string
const fd = f(d) // string
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1693 次 |
| 最近记录: |