实现类似 Vue 的类型支持的简化版本

实现类似 Vue 的类型支持的简化版本。

通过提供一个函数 SimpleVue(类似于 Vue.extenddefineComponent),它应该正确地推断出 computed 和 methods 内部的 this 类型。

在此挑战中,我们假设 SimpleVue 接受只带有 datacomputedmethods 字段的 Object 作为其唯一的参数,

  • data 是一个简单的函数,它返回一个提供上下文 this 的对象,但是你无法在 data 中获取其他的计算属性或方法。

  • computed 是将 this 作为上下文的函数的对象,进行一些计算并返回结果。在上下文中应暴露计算出的值而不是函数。

  • methods 是函数的对象,其上下文也为 this。函数中可以访问 datacomputed 以及其他 methods 中的暴露的字段。 computedmethods 的不同之处在于 methods 在上下文中按原样暴露为函数。

SimpleVue 的返回值类型可以是任意的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const instance = SimpleVue({
data() {
return {
firstname: 'Type',
lastname: 'Challenges',
amount: 10,
}
},
computed: {
fullname() {
return this.firstname + ' ' + this.lastname
}
},
methods: {
hi() {
alert(this.fullname.toLowerCase())
}
}
})

解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

type DataType<T> = T extends { data(): infer D } ? D : never;

type ComputedType<T, D> = T extends { computed: infer C }
? {
[K in keyof C]: C[K] extends (this: D) => infer R ? R : never;
}
: {};

type MethodsType<T, D, C> = T extends { methods: infer M }
? {
[K in keyof M]: M[K] extends (this: D & C) => infer R ? R : never;
}
: {};

declare function SimpleVue<T>(options: T): {
data: DataType<T>;
computed: ComputedType<T, DataType<T>>;
methods: MethodsType<T, DataType<T>, ComputedType<T, DataType<T>>>;
};