[Typescript] 88. Hard - Simple Vue
Implement a simpiled version of a Vue-like typing support.
By providing a function name SimpleVue (similar to Vue.extend or defineComponent), it should properly infer the this type inside computed and methods.
In this challenge, we assume that SimpleVue take an Object with data, computed and methods fields as it's only argument,
-
datais a simple function that returns an object that exposes the contextthis, but you won't be accessible to other computed values or methods. -
computedis an Object of functions that take the context asthis, doing some calculation and returns the result. The computed results should be exposed to the context as the plain return values instead of functions. -
methodsis an Object of functions that take the context asthisas well. Methods can access the fields exposed bydata,computedas well as othermethods. The different betweencomputedis thatmethodsexposed as functions as-is.
The type of SimpleVue's return value can be arbitrary.
const instance = SimpleVue({
data() {
return {
firstname: 'Type',
lastname: 'Challenges',
amount: 10,
}
},
computed: {
fullname() {
return this.firstname + ' ' + this.lastname
}
},
methods: {
hi() {
alert(this.fullname.toLowerCase())
}
}
})
/* _____________ Your Code Here _____________ */
type GetComputed<T> = {
[Key in keyof T]: T[Key] extends () => infer R ? R: never;
}
interface SimpleVueOptions<Data, Computed, Methods> {
data(): Data,
// Computed should able to access Data
computed: Computed & ThisType<Data & Computed>,
// Computed methods `fullname() {}` should be a prop `fullname: string` on Methods
methods: Methods & ThisType<Data & GetComputed<Computed> & Methods>
}
declare function SimpleVue<Data, Computed, Methods>(options: SimpleVueOptions<Data, Computed, Methods>): any
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
SimpleVue({
data(this: ThisType<{}>) {
// @ts-expect-error
this.firstname
// @ts-expect-error
this.getRandom()
// @ts-expect-error
this.data()
return {
firstname: 'Type',
lastname: 'Challenges',
amount: 10,
}
},
computed: {
fullname() {
return `${this.firstname} ${this.lastname}`
},
},
methods: {
getRandom() {
return Math.random()
},
hi() {
alert(this.amount)
alert(this.fullname.toLowerCase())
alert(this.getRandom())
},
test() {
const fullname = this.fullname
const cases: [Expect<Equal<typeof fullname, string>>] = [] as any
},
},
})

浙公网安备 33010602011771号