gpt4 book ai didi

typescript - 为什么这个映射类型删除了 `?` 装饰器?我们如何在不删除它的情况下获得类似的结果?

转载 作者:行者123 更新时间:2023-12-04 13:19:09 25 4
gpt4 key购买 nike

问题

我们正在构建一个映射类型,它排除了类型 Function 的属性。 .我们的方法有一个问题:它还从映射的属性中删除了可选的 ( ? ) 装饰器。

再生产

这是一个 simplified reproduction那种行为。 NoOpMap1行为符合我们的要求,并且 NoOpMap2有问题的行为。

type NoOpMap1<T> = { // Good. This one does not remove the ?
[K in keyof T]: T[K];
};

type Keys<T> = {
[K in keyof T]: K;
}[keyof T];

type NoOpMap2<T> = { // Problem. This one removes the ?
[K in Keys<T>]: T[K];
};

演示

type SomeType = {
foo?: string,
}

// type SomeTypeNoOpMap1 = { foo?: string; }
type SomeTypeNoOpMap1 = NoOpMap1<SomeType>;

// type SomeTypeNoOpMap2 = { foo: string; }
type SomeTypeNoOpMap2 = NoOpMap2<SomeType>;
NoOpMap1行为符合预期。它保留了 ?装饰器上 foo属性(property)。 NoOpMap2删除它。



为什么是 NoOpMap2删除 ?装饰师?我们如何在不删除它的情况下获得类似的结果?

实际用例

这是我们尝试构建的完整类型:

type DataPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];

type DataPropertiesOnly<T> = {
[K in DataPropertyNames<T>]
: T[K] extends (string | number | boolean) ? T[K]
: T[K] extends (infer A)[] ? DataPropertiesOnly<A>[]
: DataPropertiesOnly<T[K]>;
};

如上所述,上述类型负责删除类型 Function 的属性。不删除 ?剩余属性的装饰器。

最佳答案

如果你想在 mapped type 中保留属性的可选/只读状态,您需要确保编译器将映射视为 homomorphic .我知道有两种方法可以做到这一点。

一种是映射格式为 {[K in keyof T]: ...}您直接映射到 keyof T 的地方一些 T ,一般的或具体的。你必须有类似 in keyof 的东西直接出现在类型中,否则不会计数。

interface Foo {
optional?: string;
readonly viewonly: string;
}

type Homomorphic = { [K in keyof Foo]: 0 };
// type Homomorphic = {
// optional?: 0 | undefined;
// readonly viewonly: 0;
// }

type KeyOf<T> = keyof T
type NonHomomorphic = { [K in KeyOf<Foo>]: 0 };
// type NonHomomorphic = {
// optional: 0;
// viewonly: 0;
// }

另一种方法是映射泛型类型参数 Kconstrainedkeyof T用于另一个泛型类型参数 T .所以:
type GenericConstraint<T, K extends keyof T> = { [P in K]: 0 };
type ConstrainedHomomorphic = GenericConstraint<Foo, keyof Foo>;
// type ConstrainedHomomorphic = {
// optional?: 0 | undefined;
// readonly viewonly: 0;
// }

type OnlySomeKeysStillHomomorphic = GenericConstraint<Foo, "viewonly">;
// type OnlySomeKeysStillHomomorphic = {
// readonly viewonly: 0;
// }

后一种方法是 specifically added获取部分映射类型,如 Pick<T, K>是同态的。正是这种方法才能让您的实际用例发挥作用:
// unchanged
type DataPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];

// quick abort if T is a function or primitive
// otherwise pass to a homomorphic helper type
type DataPropertiesOnly<T> =
T extends Function ? never :
T extends object ? DPO<T, DataPropertyNames<T>> :
T

// homomorphic helper type
type DPO<T, KT extends keyof T> = {
[K in KT]
: T[K] extends (string | number | boolean) ? T[K]
: T[K] extends (infer A)[] ? DataPropertiesOnly<A>[]
: DataPropertiesOnly<T[K]>;
}

我认为这会按照你想要的方式行事。好的,希望有帮助;祝你好运!

关于typescript - 为什么这个映射类型删除了 `?` 装饰器?我们如何在不删除它的情况下获得类似的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56140221/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com