TypeScript怎么实现接口的重载入?

题目描述

TS中是怎么实现接口的重载入?

相关代码

type ItemProps = {
  a: string;
  b?: boolean;
  c?: string; 
}

const arr: ItemProps[] = [
 {
   a: 'demo',
   b: true,
   c: 'test'
 },
 {
   a: 'demo2'
 }
]

在上面定义中,怎么定义ItemProps类型才能达到: 如果b属性存在,则c属性必需存在 的效果

期待结果

const arr: ItemProps[] = [
 {
   a: 'demo',
   b: true,
   c: 'test'
 },
 {
   a: 'demo2',
   b: true, // 类型报错,因为存在b属性,但是缺少c
 } 
]; 
阅读 3.7k
2 个回答
type ExcludeKeys<T> = { [P in keyof T]: never; }

type RequireOrExcludeKeys<T, Keys extends keyof T = keyof T> =
    Pick<T, Exclude<keyof T, Keys>>
    & (Required<Pick<T, Keys>> | ExcludeKeys<Pick<T, Keys>>)

type ItemProps = RequireOrExcludeKeys<{
    a: string;
    b?: boolean;
    c?: string;
}, 'b' | 'c'>

Playground


把条件改成:如果b属性存在,则c必须存在,但是c属性存在,b可以不存在。
总结一下,就是 c 必须存在,b 可选存在。
只要修改下RequireOrExcludeKeys的参数,以及Required<Pick<T, Keys>>

type RequireOrExcludeKeys<T, RequireKeys extends keyof T = keyof T, PartialKeys extends keyof T = keyof T> =
    Pick<T, Exclude<keyof T, RequireKeys>>
    & ((Required<Pick<T, RequireKeys>> & Partial<Pick<T, PartialKeys>>)
        | ExcludeKeys<Pick<T, RequireKeys | PartialKeys>>)

type ItemProps = RequireOrExcludeKeys<{
    a: string;
    b?: boolean;
    c?: string;
}, 'c', 'b'>

Playground


type ItemProps = {
a: string;
} | {
a: string;
b: boolean;
c: string;
}


实践了一下确实不行,去查了下issue说是excess property checks不会在union types里执行

Excess property checking of unions does not work because all it does is try to find a single member of the union to check for excess properties. It does this based on discriminant properties, but A doesn't have any overlapping properties, so it can't possibly have any discriminant properties. (The same is true of the original AllowedOptions.) So excess property checking is just skipped. I chose this design because it was conservative enough to avoid bogus errors, if I remember correctly.
https://github.com/microsoft/...
似乎没有什么好的办法可以解决

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题