/* eslint-disable @typescript-eslint/ban-types */ import { expectTypeOf } from 'expect-type' import { buildProp, definePropType, mutable, keyOf, buildProps } from '../props' import type { propKey } from '../props' import type { PropType, ExtractPropTypes } from 'vue' describe('buildProp', () => { it('Only type', () => { expectTypeOf( buildProp({ type: definePropType<'a' | 'b'>(String), }) ).toEqualTypeOf<{ readonly type: PropType<'a' | 'b'> readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Only values', () => { expectTypeOf( buildProp({ values: [1, 2, 3, 4], } as const) ).toEqualTypeOf<{ readonly type: PropType<1 | 2 | 3 | 4> readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Type and values', () => { expectTypeOf( buildProp({ type: definePropType(Array), values: [1, 2, 3, 4], } as const) ).toEqualTypeOf<{ readonly type: PropType<1 | 2 | 3 | 4 | number[]> readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Values and validator', () => { expectTypeOf( buildProp({ values: ['a', 'b', 'c'], validator: (val: unknown): val is number => typeof val === 'number', } as const) ).toEqualTypeOf<{ readonly type: PropType readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Values and required', () => { expectTypeOf( buildProp({ values: ['a', 'b', 'c'], required: true, } as const) ).toEqualTypeOf<{ readonly type: PropType<'a' | 'b' | 'c'> readonly required: true readonly default?: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Value and default', () => { expectTypeOf( buildProp({ values: ['a', 'b', 'c'], required: false, default: 'b', } as const) ).toEqualTypeOf<{ readonly type: PropType<'a' | 'b' | 'c'> readonly required: false readonly default: 'b' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Type and Array default value', () => { expectTypeOf( buildProp({ type: definePropType(Array), default: () => mutable(['a', 'b'] as const), } as const) ).toEqualTypeOf<{ readonly type: PropType readonly required: false readonly default: ['a', 'b'] readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Type and Object default value', () => { interface Options { key: string } expectTypeOf( buildProp({ type: definePropType(Object), default: () => mutable({ key: 'value' } as const), } as const) ).toEqualTypeOf<{ readonly type: PropType readonly required: false readonly default: { key: 'value' } readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Type, validator and Object default value', () => { interface Options { key: string } expectTypeOf( buildProp({ type: definePropType(Object), default: () => ({ key: 'value' }), validator: (val: unknown): val is string => true, } as const) ).toEqualTypeOf<{ readonly type: PropType readonly required: false readonly default: { key: string } readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Type, validator, required', () => { expectTypeOf( buildProp({ type: definePropType<'a' | 'b' | 'c'>(String), required: true, validator: (val: unknown): val is number => true, } as const) ).toEqualTypeOf<{ readonly type: PropType readonly required: true readonly default?: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Normal type', () => { expectTypeOf( buildProp({ type: String, }) ).toEqualTypeOf<{ readonly type: PropType readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Normal types', () => { expectTypeOf(buildProp({ type: [String, Number, Boolean] })).toEqualTypeOf<{ readonly type: PropType readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Normal type and values', () => { expectTypeOf( buildProp({ type: String, values: ['1', '2', '3'], } as const) ).toEqualTypeOf<{ readonly type: PropType<'1' | '2' | '3'> readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Required and validator', () => { expectTypeOf( buildProp({ required: true, validator: (val: unknown): val is string => true, } as const) ).toEqualTypeOf<{ readonly type: PropType readonly required: true readonly default?: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Required and validator', () => { expectTypeOf( buildProp({ values: keyOf({ a: 'a', b: 'b' }), default: 'a', } as const) ).toEqualTypeOf<{ readonly type: PropType<'a' | 'b'> readonly required: false readonly default: 'a' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Type and default value', () => { expectTypeOf( buildProp({ type: definePropType<{ key: 'a' | 'b' | 'c' } | undefined>(Object), default: () => mutable({ key: 'a' } as const), } as const) ).toEqualTypeOf<{ readonly type: PropType<{ key: 'a' | 'b' | 'c' } | undefined> readonly required: false readonly default: { key: 'a' } readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('Type and default value', () => { expectTypeOf( buildProp({ type: [String, Number], default: '', } as const) ).toEqualTypeOf<{ readonly type: PropType readonly required: false readonly default: '' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('default value is empty object', () => { expectTypeOf( buildProp({ type: Object, default: () => mutable({} as const), } as const) ).toEqualTypeOf<{ readonly type: PropType> readonly required: false readonly default: {} readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true }>() }) it('extract', () => { const props = { key1: buildProp({ type: String, required: true, }), key2: buildProp({ type: [String, Number], required: true, }), } as const type Extracted = ExtractPropTypes expectTypeOf().toEqualTypeOf<{ readonly key1: string readonly key2: string | number }>() }) }) describe('buildProps', () => { it('test buildProps', () => { const propsCommon = buildProps({ type: { type: String, default: 'hello', }, } as const) const props = buildProps({ ...propsCommon, key1: { type: definePropType<'a' | 'b'>(String), }, key2: { values: [1, 2, 3, 4], }, key3: { values: [1, 2, 3, 4], default: 2, }, key4: { values: keyOf({ a: 'a', b: 'b' }), default: 'a', }, key5: Boolean, key6: String, key7: null, key8: Object, key9: Date, key10: Set, key11: undefined, // nested key12: buildProp({ type: String, } as const), // default generator key13: { type: [String, Number, Function], default: () => '123' as const, } as const, key14: { type: Function, default: () => '123' as const, } as const, key15: { type: Function, default: () => () => '123' as const, } as const, key16: { type: String, default: () => '123' as const, } as const, } as const) expectTypeOf(props).toEqualTypeOf<{ readonly type: { readonly type: PropType readonly required: false readonly default: 'hello' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key1: { readonly type: PropType<'a' | 'b'> readonly required: false readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true readonly default: undefined } readonly key2: { readonly type: PropType<1 | 2 | 3 | 4> readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key3: { readonly type: PropType<1 | 2 | 3 | 4> readonly required: false readonly default: 2 readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key4: { readonly type: PropType<'a' | 'b'> readonly required: false readonly default: 'a' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key5: BooleanConstructor readonly key6: StringConstructor readonly key7: null readonly key8: ObjectConstructor readonly key9: DateConstructor readonly key10: SetConstructor readonly key11: undefined readonly key12: { readonly type: PropType readonly required: false readonly default: undefined readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key13: { readonly type: PropType readonly required: false readonly default: '123' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key14: { readonly type: PropType readonly required: false readonly default: () => '123' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key15: { readonly type: PropType readonly required: false readonly default: () => () => '123' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } readonly key16: { readonly type: PropType readonly required: false readonly default: '123' readonly validator: ((val: unknown) => boolean) | undefined [propKey]: true } }>() }) })