打字稿`可以用不同的约束子类型实例化`错误
Posted
技术标签:
【中文标题】打字稿`可以用不同的约束子类型实例化`错误【英文标题】:Typescript `could be instantiated with a different subtype of constraint` error 【发布时间】:2021-08-14 18:26:04 【问题描述】:当我返回的结果应该符合函数的预期类型时,我不断收到could be instantiated with a different subtype of constraint
错误,我无法理解我做错了什么。这是我的代码,删除了所有不相关的细节:
type User =
interface BasePageProps
user: User
type GetServerSidePropsResult<P> =
| props: P
type PropsWithUser = <TProps extends BasePageProps>(
callback: (user: User) => Promise<Omit<TProps, 'user'>>
) => Promise<GetServerSidePropsResult<TProps>>
export const testFunc: PropsWithUser = async (callback) =>
const user =
return props:
user,
...(await callback(user))
这是我得到的错误:
' 用户:; & Omit
' 可分配给类型为“TProps”的约束,但可以使用约束“BasePageProps”的不同子类型来实例化“TProps”。
Here's this example on TS Playground.
为什么用不同子类型实例化的潜在TProps
是个问题?我该如何解决?
P.S.:您可能会注意到这些类型取自 Next.js。不过这个问题跟 Next.js 本身没有关系,所以请不要给这个问题打标签。
【问题讨论】:
【参考方案1】:你的函数的有效签名是:
type PropsWithUser = <TProps extends BasePageProps>(
callback: (user: User) => Promise<Omit<TProps, 'user'>>
) => Promise<GetServerSidePropsResult<BasePageProps & Omit<TProps, 'user'>>>
或者你可以删除一些重复:
type PropsWithUser = <TProps extends BasePageProps, TO = Omit<TProps, 'user'>(
callback: (user: User) => Promise<TO>
) => Promise<GetServerSidePropsResult<BasePageProps & TO>>
证明编译器正确引发代码错误的反例。让我们定义一个扩展 BasePageProps
但不通过函数结果类型检查的 TProps
类型的具体示例:
type User =
type AnotherUser = a: string
interface TProps
user: AnotherUser
interface BasePageProps
user: User
type Eq = TProps extends BasePageProps ? true : false // type Eq = true
type PropsWithUser = <TProps extends BasePageProps>(
callback: (user: User) => Promise<Omit<TProps, 'user'>>
) => Promise<GetServerSidePropsResult<TProps>>
TS playground
所以你的函数应该返回类型为Promise< props: user: AnotherUser, ... >
的结果。它显然没有。
正如错误所说:' user: ; & Omit<TProps, "user">' is assignable to the constraint of type 'TProps', but 'TProps' could be instantiated with a different subtype of constraint 'BasePageProps'
type User =
interface BasePageProps
user: User
type AnotherUser = a: string
interface ConcreteTProps
user: AnotherUser
// user: ; & Omit<TProps, "user"> is assignable
// to the constraint of type TProps (i.e. BasePageProps)
const a: BasePageProps = user:
// but 'TProps' could be instantiated with a different
// subtype of constraint 'BasePageProps' (i.e. ConcreteTProps)
// Which is a subtype of BasePageProps by cannot be
// assigned with user: User
const b: ConcreteTProps = user: // error
【讨论】:
没想到字段的类型也可以在扩展接口上扩展,谢谢!以上是关于打字稿`可以用不同的约束子类型实例化`错误的主要内容,如果未能解决你的问题,请参考以下文章