如何在类型级别断言一个类型不是任何类型?

How to type-level assert a type is not any?

我正在使用类型级 Assert 函数对我的代码中的类型推断进行断言。但是,我无法对不是 any.

的类型做出任何断言
type Assert<A extends ShouldBe, ShouldBe> = A

// @ts-expect-error
type SubsetObj = Assert<{ id: string }, { id: string; name: string }>
type SameObj = Assert<
    { id: string; name: string },
    { id: string; name: string }
>
type ExceedsObj = Assert<{ id: string; name: string }, { id: string }>

type SubsetUnion = Assert<number, number | string>
type SameUnion = Assert<number | string, number | string>

// @ts-expect-error
type ExceedUnion = Assert<number | string, number>

// @ts-expect-error  this is what I want to work.
type AnyShouldWork = Assert<any, number>

我已经尝试了一些无济于事的事情。我注意到 unknown 按预期工作

// @ts-expect-error
type AssertUnknown = Assert<unknown, number>

所以我尝试了这段代码:

type IsAny<T> = unknown extends T ? (T extends {} ? T : never) : never
type NotAny<T> = T extends IsAny<T> ? unknown : T

type Assert2<A extends ShouldBe, ShouldBe> = Assert<NotAny<A>, ShouldBe>

// @ts-expect-error
type AssertAny = Assert2<any, number>

但这不起作用,因为 Assert<NotAny<A>, ShouldBe> 立即失败,因为 NotAny 可以 return 未知...

所以我有点卡在这里...有什么想法吗?

我认为使用额外的 Equals 助手更好更容易:


// credits goes to https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
export type Equals<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false;


type AssertTrue<A extends true> = A

// @ts-expect-error
type Test1 = AssertTrue<Equals<any, number>>
// @ts-expect-error
type Test2 = AssertTrue<Equals<unknown, number>>
// @ts-expect-error
type Test3 = AssertTrue<Equals<number | string, number>>
// @ts-expect-error
type Test4 = AssertTrue<Equals<{ id: string }, { id: string; name: string }>>