type ComputedResults<F> = {
[k in keyof F]: F[k] extends (...args: any[]) => infer R ? R : never;
}
type SimpleVueOptions<D, C, M> = {
data: (this: void) => D;
computed: C & ThisType<D & ComputedResults<C>>;
methods: M & ThisType<D & M & ComputedResults<C>>;
}
declare function SimpleVue<D, C, M>(
options: SimpleVueOptions<D, C, M>
): void
Solution by wendao-liu #35164
// your answers
Solution by Topolev #35020
// 你的答案
declare function SimpleVue<D, C, M>(options: {
data: (this: void) => D;
computed: C & ThisType<D>;
methods: M &
ThisType<
D &
M & {
[P in keyof C]: C[P] extends (...args: any[]) => infer R ? R : never;
}
>;
}): any;
Solution by larryerik #34328
type Computed<C> = C extends Record<string, (...args: any[]) => any> ? {
[K in keyof C]: ReturnType<C[K]>
} : never
declare function SimpleVue<D, C, M>(options: {
data(this: {}): D,
computed: C,
methods: M
} & ThisType<D & Computed<C> & M>): any
Solution by ouzexi #34193
// 你的答案
declare function SimpleVue<D,C,M>(options: {
data: (this: null) => D,
// computed中的this可以指向data,并且还可以指向计算属性,准确的说是指向计算属性的返回值 this.fullname.firstname
computed: C & ThisType<D & getComputedReturn<C>>,
methods: M & ThisType<D & getComputedReturn<C> & M>
}): any
// 获取到计算属性的返回值类型
type getComputedReturn<T> = {
[key in keyof T]: T[key] extends (...args: any[]) => infer R ? R : never
}
Solution by chenjieya #33455
type Computed<T> = {
[P in keyof T]: T[P] extends () => infer V ? V : never
}
type Options<D, C, M> = {
data: (this: {}) => D,
computed: ThisType<D & Computed<C> & M> & C,
methods: ThisType<D & Computed<C> & M> & M
}
declare function SimpleVue<D, C, M>(options: Options<D, C, M>): any
Solution by machine-solution #32961
type AmendComputed<T> = {
[P in keyof T]: T[P] extends (...arg: any[]) => infer R ? R : T[P];
};
type Options<VData, VComputed, VMethod> = {
data: (this: void) => VData;
computed: VComputed & ThisType<VData & AmendComputed<VComputed>>;
methods: VMethod & ThisType<VData & AmendComputed<VComputed> & VMethod>;
};
declare function SimpleVue<VData, VComputed, VMethod>(
options: Options<VData, VComputed, VMethod>
): unknown;
Solution by Vampirelee #32598
type ID = object | (() => object);
type IC = Record<string, Function>;
type IM = Record<string, Function>;
type Mixed<
D extends ID,
C extends IC,
M extends IM,
> = &
(D extends () => object ? ReturnType<D> : D) &
{ readonly [key in keyof C]: C[key] extends () => any ? ReturnType<C[key]> : never } &
M;
type Args<
D extends ID,
C extends IC,
M extends IM,
> = {
data: D,
computed: C,
methods: M,
}
declare function SimpleVue<
D extends ID,
C extends IC,
M extends IM,
>(value: Args<D, C, M> & ThisType<Mixed<D, C, M>>): Mixed<D, C, M>;
const instance = SimpleVue({
data() {
return {
firstname: 'Type',
lastname: 'Challenges',
amount: 10,
}
},
computed: {
fullname() {
this.lastname = '1'
return this.firstname + ' ' + this.lastname
}
},
methods: {
hi() {
// Test internal this types
this.firstname = 'test'
alert(this.fullname.toLowerCase())
},
hi2(a: number) {
return a.toString()
}
}
})
// Test some output types
const a = instance.amount;
const f = instance.fullname
const hi = instance.hi
const hi2 = instance.hi2
Solution by alexbidenko #32560
// your answers
type GetComputed<C> = C extends { [S in keyof C]: (...args: any[]) => any }
? { [S in keyof C]: ReturnType<C[S]> }
: never
declare function SimpleVue<D, C, M>(
options: {
data: () => D,
computed: C,
methods: M,
} & ThisType<D & M & GetComputed<C>>
): any
const vue = SimpleVue({
data() {
return {
firstname: 'Type',
lastname: 'Challenges',
amount: 10,
symbol: Symbol('fff')
}
},
computed: {
fullname() {
return this.firstname + ' ' + this.lastname
},
amountPlusOne() {
let amount = this.plusOne()
return amount
},
fullnameAsNickname() {
return Symbol(this.fullname)
}
},
methods: {
plusOne() {
return this.amount + 1
},
hi() {
alert(this.fullname.toLowerCase())
},
alert() {
this.hi()
}
}
})
// { [S in keyof C]: (...args: any[]) => any }
// like
// Record<string, (...args: any[]) => any>
Solution by laqudee #32356
declare function SimpleVue<D, C, M>(options: {
data: (this: void) => D;
computed: C & ThisType<D>;
methods: M &
ThisType<
D &
M & {
[K in keyof C]: C[K] extends (...args: any[]) => any
? ReturnType<C[K]>
: never;
}
>;
}): any;
Solution by vangie #32217
// your answers
type ComputedValue<Computed> = {
[Properties in keyof Computed]: Computed[Properties] extends (...args: any[]) => infer R ? R : never
}
type VueOptions<Data, Computed, Method> = {
data: (this: void) => Data
computed: Computed & ThisType<Data>
methods: Method & ThisType<Data & Method & ComputedValue<Computed>>
}
declare function SimpleVue<Data, Computed, Method>(options: VueOptions<Data, Computed, Method>): any
Solution by trinhvinhtruong96 #32027
type ComputedValueType<C> = {
[P in keyof C as C[P] extends () => any
? P
: never]: C[P] extends () => infer R ? R : never;
};
declare function SimpleVue<Data,Computed,Methods>(options: {
data : (this:void) => Data & ThisType<Data>,
computed: Computed & ThisType<Computed & Data>,
methods: Methods & ThisType<ComputedValueType<Computed> & Methods & Data>
}): Data & Computed & Methods
Solution by chliguiy #31130
type OptionsType<C,D,M> = {
data:(this:unknown)=> C,
computed:D & ThisType<C>,
methods:M & ThisType<C & {[Key in keyof D] : D[Key] extends (...args:any[])=>infer V ? V : never} & M>,
}
declare function SimpleVue<C,D,M>(options: OptionsType<C,D,M>): any
Solution by idebbarh #30308
declare function SimpleVue<Data, Computed extends Record<string, (this: Data) => any>, Methods extends Record<string, () => any>>(options: {
data: (this: undefined) => Data
computed: Computed,
methods: Methods & { [key in keyof Methods]: (this: Data & { [key in keyof Computed]: ReturnType<Computed[key]> } & Methods) => any }
}): any
Solution without ThisType
Solution by shokhboz-abdullaev #29902
declare function SimpleVue<
D extends Record<string, unknown>,
C extends Record<string, unknown>,
M extends Record<string, () => void>,
>(options: {
data?: (this: never) => D;
computed?: {
[K in keyof C]: (this: D) => C[K];
};
methods?: M & ThisType<M & D & C>;
}): any;
Solution by nia3y #29200
type GetComputed<Computed> = Computed extends Record<string, (...args: unknown[]) => unknown>
? { [Key in keyof Computed]: ReturnType<Computed[Key]> }
: never
type OptionsType<TData, TComputed, TMethods> = {
data: (this: null) => TData
computed: TComputed
methods: TMethods
} & ThisType<TData & GetComputed<TComputed> & TMethods>
declare function SimpleVue<TData, TComputed, TMethods>(options: OptionsType<TData, TComputed, TMethods>): any
Solution by aybykovskii #28809
Don't even try. Just watch this one. So far as anyone can tell, there's no way to accomplish this one without use of a special (and extremely rare) type that the TypeScript compiler has special knowledge of.
// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'
SimpleVue({
data() {
// @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
type C1 = Expect<Equal<typeof fullname, string>>
},
},
});
// ============= Your Code Here =============
declare function SimpleVue<
Data,
Computed extends
Record<PropertyKey, (...args: unknown[]) => unknown>,
Methods
>(
options: {
data: (this: void) => Data;
computed: Computed & ThisType<Data>;
methods:
Methods
& ThisType<
& Data
& Methods
& {
[P in keyof Computed]:
ReturnType<Computed[P]>
}
>;
}
): unknown;
For more video solutions to other challenges: see the umbrella list! https://github.com/type-challenges/type-challenges/issues/21338
Solution by dimitropoulos #26113
interface Options<D, C extends Record<PropertyKey, () => unknown>, M> {
data: (this: never) => D,
computed: C & ThisType<D>,
methods: M & ThisType<D & {[Key in keyof C]: ReturnType<C[Key]>} & M>
};
declare function SimpleVue<D, C extends Record<PropertyKey, () => unknown>, M>(options: Options<D, C, M>): unknown
Solution by bryzZz #25931
type ReturnType<F> = F extends (...args: infer A) => infer R ? R : F
type GetValues<C extends Record<PropertyKey, any>> = { [K in keyof C]: ReturnType<C[K]> }
type Computed<C extends Record<PropertyKey, any>, T> =
{ [K in keyof C]: (this: T, ...args: unknown []) => ReturnType<C[K]> }
type Methods<M extends Record<PropertyKey, any>, T> =
{ [K in keyof M]: (this:T, ...args: unknown []) => ReturnType<M[K]> }
type Data<D> = (this: Data<D>, ...args: unknown[]) => D
declare function SimpleVue<
D extends Record<PropertyKey, any>,
C extends Record<PropertyKey, any>,
M extends Record<PropertyKey, any>
>(options: {
data: Data<D>,
computed: Computed<C, D>,
methods: Methods<M, D & GetValues<C> & Methods<M, D & GetValues<C>>>
}): Data<D> & Computed<C, D> & Methods<M, D & GetValues<C> & Methods<M, D & GetValues<C>>>
Solution by JhonLandy #25872
type Computed<C extends Record<PropertyKey, () => any>> = {
[CK in keyof C]: ReturnType<C[CK]>;
};
type SimpleVueOptions<
D extends Record<PropertyKey, any>,
C extends Record<PropertyKey, () => any>,
M extends Record<PropertyKey, () => any>
> = {
data: () => D;
computed: C & ThisType<D>;
methods: M & ThisType<D & Computed<C> & M>;
} & ThisType<null>;
declare function SimpleVue<
D extends Record<PropertyKey, any>,
C extends Record<PropertyKey, () => any>,
M extends Record<PropertyKey, () => any>
>(options: SimpleVueOptions<D, C, M>): any;
Solution by Creo-KR #25209
declare function SimpleVue<
D,
C extends Record<PropertyKey, (...args: any) => any>,
M
>(options: {
data: (this: void) => D;
computed: C & ThisType<D>;
methods: M & ThisType<D & M & { [K in keyof C]: ReturnType<C[K]> }>;
}): any;
Solution by ickynavigator #25031
// your answers
// your answers
declare function SimpleVue<
T extends { [x: PropertyKey]: any },
U extends { [x: string]: () => any },
V extends { [x: string]: () => any }
>(
options: {
data: () => T
computed: U & ThisType<T>
methods: V &
ThisType<
T &
V & {
[P in keyof U]: U[P] extends () => infer R ? R : never
}
>
} & ThisType<never>
): any
Solution by studymachiney #24950
declare function SimpleVue<
T extends { [x: PropertyKey]: any },
U extends { [x: string]: () => unknown },
V extends { [x: string]: () => unknown }>(options: {
data: () => T,
computed: U & ThisType<T>,
methods: V & ThisType<V & T & { [P in keyof U]: U[P] extends () => infer R ? R : never }>
} & ThisType<never>): any
Solution by E-uler #24573
// 你的答案
declare function SimpleVue<
D extends Record<string,unknown>,
C extends Record<string,unknown>,
M extends Record<string,unknown>
>(options: {
data:(this:never)=>D
computed:{
[key in keyof C]:(this:D)=>C[key]
}
methods:{
[key in keyof M]:(this:D&C&{[K in keyof M]:()=>M[K]})=>M[key]
}
}): any
Solution by walker-hzx #24279
type Computed<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => infer R ? R : T[K]
}
interface Options<D, C, M> {
data?: () => D
computed?: C & ThisType<D & Computed<C> & M>
methods?: M & ThisType<D & Computed<C> & M>
}
declare function SimpleVue<D, C, M> (options: Options<D, C, M>): any
Solution by drylint #23161
// 你的答案
type FunctionReturn<T> = T extends (...args: any) => infer R ? R : T;
declare function SimpleVue<
D,
M,
C
>(options: {
data: D,
methods: M,
computed: C,
} & ThisType<
FunctionReturn<D> & M & {[key in keyof C]: FunctionReturn<C[key]>} & {
data: D,
methods: M,
computed: C
}> ): any
Solution by 437204933 #21979
// 你的答案
// 0 一开始只添加了 D,可是写methods时这货竟然需要 computed的类型,
// 1 然后又发现这货又用this 调用自己的函数, 于是又加了M才把红线消除完毕.
declare function SimpleVue<D, C, M>(options: TestOption<D, C, M>): TestOption<D, C, M>
// 2 起初看不懂这题到底要干啥,后来看着看着发现这题是想解决this问题
type TestOption<D, C, M> = {
data?: D,
// 3 如果 D是函数类型, 那么 computed 的 this 应该是它本身和 D的返回值或D本身
computed?: C & ThisType<D extends () => infer R ? R : D>,
// 4 methods里的this 同样也是 M本身
// 5 和 D...
// 6 和 C里面的各种函数 改为 函数名:函数返回值类型的 新类型
methods?: M & ThisType<
(D extends () => infer R ? R : D)
& { [K in keyof C]: C[K] extends (...argv: any) => infer R ? R : C[K] }
& M // 7 写到这里,发现错误信息都没了.
>,
}
Solution by goddnsgit #21834
// your answers
type Options<D,C,M> = {
data(this:never):D
computed:C & ThisType<D>,
methods:{
[K in keyof M]:M[K]
} & ThisType<D & M & {
[K1 in keyof C] : C[K1] extends () => any ? ReturnType<C[K1]> : C[K1]
}>
}
declare function SimpleVue<D,C,M>(options: Options<D,C,M>): any
Solution by YqxLzx #21315
type RecordFunction = Record<string,Function>;
type TransitionComputed<T extends RecordFunction> = {
[P in keyof T]:T[P] extends ()=>infer A ? A :never
};
type Vue<
Data extends Record<string,any>,
Computed extends RecordFunction,
Methods extends RecordFunction,
> = {
data?():Data;
computed?: Computed & ThisType<Methods & TransitionComputed<Computed> & Data>,
methods?: Methods & ThisType<Methods & TransitionComputed<Computed> & Data>,
}
declare function SimpleVue<
Data extends Record<string,any>,
Computed extends RecordFunction,
Methods extends RecordFunction,
>(options: Vue<Data,Computed,Methods>): any
Solution by so11y #20969
type VueOptions<D, C, M> = {
data: (this: {}) => D,
computed: C & ThisType<D>,
methods: M & ThisType<D & M & ComputedValues<C>>
}
interface MyVue {
new <D, C, M>(options: VueOptions<D, C, M>): any
}
declare const MyVue: MyVue
const instance1 = new MyVue({
data() {
return {
firstname: 'Type',
lastname: 'Challenges',
amount: 10,
}
},
computed: {
fullname() {
return this.firstname + ' ' + this.lastname
}
},
methods: {
hi() {
alert(this.fullname.toLowerCase())
}
}
})
Solution by m7yue #20367