Typescript 为什么此映射类型要删除“?”装饰符?我们如何才能在不删除它的情况下实现类似的结果? 问题
我们正在构建一个映射类型,该类型不包括Typescript 为什么此映射类型要删除“?”装饰符?我们如何才能在不删除它的情况下实现类似的结果? 问题,typescript,types,mapped-types,Typescript,Types,Mapped Types,我们正在构建一个映射类型,该类型不包括函数类型的属性。我们的方法有一个问题:它还从映射属性中删除可选(?)装饰器 繁殖 下面是这种行为的一个例子NoOpMap1的行为符合我们的要求,NoOpMap2的行为有问题 键入NoOpMap1={//Good。这一个不会删除? [K in keyof T]:T[K]; }; 类型键={ [K in keyof T]:K; }[keyof T]; 键入NoOpMap2={//Problem。此操作将删除? [K in键]:T[K]; }; 演示 type
函数
类型的属性。我们的方法有一个问题:它还从映射属性中删除可选(?
)装饰器
繁殖
下面是这种行为的一个例子NoOpMap1
的行为符合我们的要求,NoOpMap2
的行为有问题
键入NoOpMap1={//Good。这一个不会删除?
[K in keyof T]:T[K];
};
类型键={
[K in keyof T]:K;
}[keyof T];
键入NoOpMap2={//Problem。此操作将删除?
[K in键]:T[K];
};
演示
type SomeType={
foo?:字符串,
}
//键入SomeTypeNoOpMap1={foo?:string;}
键入SomeTypeNoOpMap1=NoOpMap1;
//键入SomeTypeNoOpMap2={foo:string;}
键入SomeTypeNoOpMap2=NoOpMap2;
NoOpMap1
的行为符合预期。它将?
装饰器保留在foo
属性上<代码>NoOpMap2将其删除
问题:
为什么NoOpMap2
正在删除?
装饰器?我们如何才能在不删除它的情况下实现类似的结果
实际用例
以下是我们尝试构建的完整类型:
类型DataPropertyNames={
[K in keyof T]:T[K]扩展函数?never:K;
}[keyof T];
类型DataPropertiesOnly={
[DataPropertyNames中的K]
:T[K]扩展(字符串|数字|布尔值)?T[K]
:T[K]扩展(推断A)[]?DataPropertiesOnly[]
:仅限DataProperties;
};
如上所述,上述类型负责删除
Function
类型的属性,而无需从其余属性中删除?
装饰器。如果要在中保留属性的可选/只读状态,则需要确保编译器将映射视为。我知道两种方法
一种是映射形式为{[K in keyof T]:…}
,其中您直接映射一些T
,通用或具体的keyof 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;
// }
后一种方法是将部分映射类型(如Pick
)设置为同态。正是这种方法让您的实际用例发挥作用:
// 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]>;
}
//未更改
类型DataPropertyNames={
[K in keyof T]:T[K]扩展函数?never:K;
}[keyof T];
//如果T是函数或原语,则快速中止
//否则传递给同态助手类型
仅键入DataProperties=
T扩展函数?从未:
T扩展对象?DPO:
T
//同态辅助型
DPO类型={
[K单位:KT]
:T[K]扩展(字符串|数字|布尔值)?T[K]
:T[K]扩展(推断A)[]?DataPropertiesOnly[]
:仅限DataProperties;
}
我想那会按照你的意愿行事。好吧,希望这会有帮助;祝你好运 你学习过范畴理论吗?没有正式学习;我希望我在这方面有更扎实的背景,因为事实证明这和计算机编程语言类型系统中发生的许多事情有关。
// 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]>;
}