扩展字符串文本的条件类型



我想添加一个类型实用程序,它应该有条件地添加T

请参阅Codesandbox

想法如下:

类似这样的东西:type IfType<If, Eq, T>

  • Ifstring literal的一种类型,例如"Cat" | "Dog"
  • Eq是提取的If的字符串文字,例如"Cat""Dog"
  • 如果传递的generic type是特定类型的,则T是我想要返回的类型

T扩展了object,但如果Eq不是equal,则返回Partial<T>,因此该类型仍然知道object密钥(用于析构函数(。

类似这样的东西:

util.ts

type IfType<
If extends string,
Eq extends If,
T extends object
> = If extends Extract<If, Eq> ? T : Partial<T>

otherfile.ts

type Type = 'read' | 'write';
type Props<T extends Type> = { 
type: T 
} & (
IfType<
T,
// This gets the ts(2344) error, and I don't know how to stop it
"write",
{ descriptionOnlyForWrite: string }
> 
| IfType<
T,
// This gets the ts(2344) error, and I don't know how to stop it
"read",
{ hasRead: boolean}
>);

这给出了以下错误:

Type '"write"' does not satisfy the constraint 'T'.
'"write"' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Type'.

关于如何键入helper util类型,有什么建议吗?

额外信息:如果没有utils类型,我通常会如何键入它,它可以按照我的要求工作

type Type = 'read' | 'write';
type Props<T extends Type> = {
type: T;
} & (
| (T extends 'write' ? { descriptionOnlyForWrite: string } : { descriptionOnlyForWrite?: undefined })
| (T extends 'read' ? { hasRead: boolean } : { hasRead?: undefined })
);

T extends Type"write" extends Type并不意味着"write" extends T。考虑当T"read"(作为Props<"read">(时会发生什么;"write" extends "read"不是真的,所以编译器抱怨IfType<T, "write", XXX>可能无效。

看起来你并不是真的希望IfType<If, Eq, T>需要Eq extends If。假设你不想让IfType变得更复杂,你可以去掉对Eq:的限制

type IfType<
If extends string,
Eq, // <-- no constraint here
T extends object
> = If extends Extract<If, Eq> ? T : Partial<T>

然后根据需要编译以下内容:

type Props<T extends Type> = { type: T } & (
IfType<T, "write", { descriptionOnlyForWrite: string }>
| IfType<T, "read", { hasRead: boolean }>
);

如果您真的关心在IfEq上表达约束,则需要将该约束作为单独的类型参数C传递给IfType:

type IfType<
C extends string,
If extends C,
Eq extends C,
T extends object
> = If extends Extract<If, Eq> ? T : Partial<T>
type Props<T extends Type> = { type: T } & (
IfType<Type, T, "write", { descriptionOnlyForWrite: string }>
| IfType<Type, T, "read", { hasRead: boolean }>
);

但我怀疑这对于您的用例是否真的有必要。毕竟,IfType从未实际使用C来计算输出类型;这只是对CCD_ 38和CCD_。除非你有什么重要的理由这样做,否则我只会完全取消对Eq的限制。

游乐场链接到代码

最新更新