这应该按预期工作:
type NotFunctions<T, E extends keyof T> = {
[P in Exclude<keyof T, E>]-?: T[P] extends Function ? never : P
}[Exclude<keyof T, E>]
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type Unwrap<T> = T extends { toJSON(): infer U } ? U : T;
type PickAndUnwrap<T, K extends keyof T> = {
[P in K] : Unwrap<T[P]>
}
type SimpleOrComplex<T, E extends keyof T> = NotFunctions<T, E> extends UnionToIntersection<NotFunctions<T, E>>?
PickAndUnwrap<T, NotFunctions<T, E>>[NotFunctions<T, E>] :
PickAndUnwrap<T, NotFunctions<T, E>>
type Id<T> = T extends object ? {} & { [P in keyof T] : T[P]} : T
class TinyType {
public toJSON(): Id<SimpleOrComplex< this, keyof TinyType>> {
return null!;
}
}
class Name extends TinyType {
constructor(public readonly name: string) {
super();
}
}
new Name('Bob').toJSON() === ""
class Age extends TinyType {
constructor(public readonly age: number) {
super()
}
}
new Age(42).toJSON() === 42
class Integer extends TinyType {
constructor(public readonly value: number) {
super();
}
}
class AmountInCents extends TinyType {
constructor(public readonly amountInCents: Integer) {
super();
}
}
class Credit extends TinyType {
constructor(public readonly amount: AmountInCents) {
super()
}
}
new AmountInCents(new Integer(100)).toJSON
new Credit(new AmountInCents(new Integer(100))).toJSON() === 100
class Timestamp extends TinyType {
constructor(public readonly value: Integer) {
super();
}
}
class CreditRecorded extends TinyType {
constructor(
public readonly credit: Credit,
public readonly timestamp: Timestamp,
) {
super();
}
}
new CreditRecorded(
new Credit(new AmountInCents(new Integer(100))),
new Timestamp(new Integer(1234567)),
).toJSON() === { credit: 100, timestamp: 1234567 }
class Person extends TinyType {
constructor(
public readonly name: Name,
public readonly creditRecord: CreditRecorded,
public readonly age: Integer) {
super();
}
}
new Person(new Name(""), new CreditRecorded(
new Credit(new AmountInCents(new Integer(100))),
new Timestamp(new Integer(1234567)),
), new Integer(23)).toJSON()
只是一些警告,没有广泛的测试,所以你可能会
any
在某种程度上,如果编译器认为类型太复杂。
Id
只是为了美观的原因才把它弄平,如果你遇到问题,就用它吧
Id<T> = T
看看塔特能不能修好。
如果您有任何问题,请告诉我,我会尽力回答,解决方案基本上只是一个映射和条件类型的直接应用程序,就像您认为的那样。