TypeScript -具有可选never值的记录或Map类型

ehxuflar  于 2023-03-19  发布在  TypeScript
关注(0)|答案(1)|浏览(144)

我正在构建一个类型帮助器,它将接口/对象类型与记录合并,其中记录的值参数应该是可选的never类型。这个实用程序是作为一种速记使用的,这样你就不必为每个属性输入key?: never
这是我的进展。

type WithOptionalNever<T, Keys extends string> = T &
  Partial<Record<Keys, never>>

interface PropsWithout extends WithOptionalNever<Props, "ipsum" | "dolor"> {
  lorem: false
}

这将生成以下类型:

lorem: false;
ipsum: never;
dolor: never;

这是意料之中的,我的思路是将记录 Package 在Partial中,但这并没有提供所需的结果:

lorem: false;
ipsum?: undefined;
dolor?: undefined;

我尝试过用Map类型实现同样的效果,但似乎结果与Partial<Record<Keys, Never>>相同。
有什么想法?
编辑:
我被要求澄清我想如何继续下去,似乎我所要求的不是预期的行为,也没有妨碍我试图实现的目标。
这里有一个简单的例子。我认为key?: never不允许传递lorem prop,除非more显式设置为true。我想我的问题是,是否有一种方法可以完全禁止传递基于另一个属性的缺失/值的属性?

interface Props {
  lorem: string
  more?: boolean
}

interface PropsWith extends Props {
  more: true
  ipsum: string
}

interface PropsWithOut extends Props {
  more?: false
  ipsum?: never
}

export default function Lorem(props: PropsWith | PropsWithOut) {
  return <></>
}

function Test() {
  return (
    <> 
      // I misunderstood and though ?: never would deny the passing of prop
      <Lorem lorem="fndjsk" ipsum={undefined} />
      <Lorem lorem="fndjsk" more={true} ipsum="hfjdsk" />
    </>
  )
}
twh00eeo

twh00eeo1#

它在TypeScript的类型系统上下文中有意义。
WithOptionalNever类型帮助器的目标是允许以一种简化的方式将某些属性标记为可选的,这在某些情况下非常有用。但是,仅将记录 Package 在Partial中无法实现所需的结果,因为这将使所有属性都是可选的,而不仅仅是Keys中指定的属性。
相反,一种可能的解决方案是使用“拾取”和“忽略”将原始类型拆分为两个部分:一个有可选的never属性,一个没有。然后,我们可以使用交集(&)将它们合并在一起来创建最终类型。
下面是一个示例实现:

type WithOptionalNever<T, Keys extends keyof T> = Pick<T, Exclude<keyof T, Keys>> &
  Partial<Pick<T, Keys>> &
  Record<Exclude<keyof T, Keys>, never>

interface Props {
  foo: string;
  bar: number;
  baz: boolean;
}

// Example usage
type PropsWithout = WithOptionalNever<Props, "bar" | "baz">

// Resulting type:
// {
//   foo: string;
//   bar?: number | undefined;
//   baz?: boolean | undefined;
//   // Properties not included in "Keys" are marked as never
// }

此实现使用Pick和Omit将原始Props类型拆分为两部分。第一部分包括除Keys中指定的属性(即“bar”和“baz”)之外的所有属性。第二部分仅包括Keys中指定的属性,但使用Partial标记为可选。
最后,我们使用交集(&)将这两个部分重新合并在一起,并添加一个Record来将所有剩余的属性(即“foo”)标记为never。
这将导致所有指定属性都标记为可选的类型,而保留原始类型结构的其余部分。

相关问题