mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
refactor(utils): improve defineProps (#3811)
* refactor(utils): improve defineProps * refactor(utils): improve defineProps
This commit is contained in:
@@ -20,7 +20,8 @@ type ResolvePropTypeWithReadonly<T> = Readonly<T> extends Readonly<
|
||||
>
|
||||
? ResolvePropType<A[]>
|
||||
: ResolvePropType<T>
|
||||
type IfUnknown<T, V> = [unknown] extends T ? V : T
|
||||
|
||||
type IfUnknown<T, V> = [unknown] extends [T] ? V : T
|
||||
|
||||
export type BuildPropOption<T, D extends BuildPropType<T, V, C>, R, V, C> = {
|
||||
type?: T
|
||||
@@ -30,7 +31,7 @@ export type BuildPropOption<T, D extends BuildPropType<T, V, C>, R, V, C> = {
|
||||
? never
|
||||
: D extends Record<string, unknown> | Array<any>
|
||||
? () => D
|
||||
: D
|
||||
: (() => D) | D
|
||||
validator?: ((val: any) => val is C) | ((val: any) => boolean)
|
||||
}
|
||||
|
||||
@@ -48,22 +49,32 @@ export type BuildPropType<T, V, C> = _BuildPropType<
|
||||
IfUnknown<C, never>
|
||||
>
|
||||
|
||||
export type BuildPropDefault<D, R> = R extends true
|
||||
type _BuildPropDefault<T, D> = [T] extends [
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
Record<string, unknown> | Array<any> | Function
|
||||
]
|
||||
? D
|
||||
: D extends () => T
|
||||
? ReturnType<D>
|
||||
: D
|
||||
|
||||
export type BuildPropDefault<T, D, R> = R extends true
|
||||
? { readonly default?: undefined }
|
||||
: {
|
||||
readonly default: Exclude<D, undefined> extends never
|
||||
? undefined
|
||||
: Exclude<
|
||||
D extends Record<string, unknown> | Array<any> ? () => D : D,
|
||||
undefined
|
||||
>
|
||||
: Exclude<_BuildPropDefault<T, D>, undefined>
|
||||
}
|
||||
export type BuildPropReturn<T, D, R, V, C> = {
|
||||
readonly type: PropType<BuildPropType<T, V, C>>
|
||||
readonly required: IfUnknown<R, false>
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
} & BuildPropDefault<IfUnknown<D, never>, IfUnknown<R, false>>
|
||||
} & BuildPropDefault<
|
||||
BuildPropType<T, V, C>,
|
||||
IfUnknown<D, never>,
|
||||
IfUnknown<R, false>
|
||||
>
|
||||
|
||||
/**
|
||||
* @description Build prop. It can better optimize prop types
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
|
||||
import { expectTypeOf } from 'expect-type'
|
||||
import { buildProp, definePropType, mutable, keyOf, buildProps } from '../props'
|
||||
import type { propKey } from '../props'
|
||||
@@ -103,7 +105,7 @@ describe('buildProp', () => {
|
||||
).toEqualTypeOf<{
|
||||
readonly type: PropType<string[]>
|
||||
readonly required: false
|
||||
readonly default: () => ['a', 'b']
|
||||
readonly default: ['a', 'b']
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}>()
|
||||
@@ -122,7 +124,7 @@ describe('buildProp', () => {
|
||||
).toEqualTypeOf<{
|
||||
readonly type: PropType<Options>
|
||||
readonly required: false
|
||||
readonly default: () => { key: 'value' }
|
||||
readonly default: { key: 'value' }
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}>()
|
||||
@@ -141,7 +143,7 @@ describe('buildProp', () => {
|
||||
).toEqualTypeOf<{
|
||||
readonly type: PropType<string | Options>
|
||||
readonly required: false
|
||||
readonly default: () => { key: string }
|
||||
readonly default: { key: string }
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}>()
|
||||
@@ -241,7 +243,7 @@ describe('buildProp', () => {
|
||||
).toEqualTypeOf<{
|
||||
readonly type: PropType<{ key: 'a' | 'b' | 'c' } | undefined>
|
||||
readonly required: false
|
||||
readonly default: () => { key: 'a' }
|
||||
readonly default: { key: 'a' }
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}>()
|
||||
@@ -262,6 +264,21 @@ describe('buildProp', () => {
|
||||
}>()
|
||||
})
|
||||
|
||||
it('default value is empty object', () => {
|
||||
expectTypeOf(
|
||||
buildProp({
|
||||
type: Object,
|
||||
default: () => mutable({} as const),
|
||||
} as const)
|
||||
).toEqualTypeOf<{
|
||||
readonly type: PropType<Record<string, any>>
|
||||
readonly required: false
|
||||
readonly default: {}
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}>()
|
||||
})
|
||||
|
||||
it('extract', () => {
|
||||
const props = {
|
||||
key1: buildProp({
|
||||
@@ -318,6 +335,24 @@ describe('buildProps', () => {
|
||||
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<{
|
||||
@@ -371,6 +406,34 @@ describe('buildProps', () => {
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}
|
||||
readonly key13: {
|
||||
readonly type: PropType<string | number | Function>
|
||||
readonly required: false
|
||||
readonly default: '123'
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}
|
||||
readonly key14: {
|
||||
readonly type: PropType<Function>
|
||||
readonly required: false
|
||||
readonly default: () => '123'
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}
|
||||
readonly key15: {
|
||||
readonly type: PropType<Function>
|
||||
readonly required: false
|
||||
readonly default: () => () => '123'
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}
|
||||
readonly key16: {
|
||||
readonly type: PropType<string>
|
||||
readonly required: false
|
||||
readonly default: '123'
|
||||
readonly validator: ((val: unknown) => boolean) | undefined
|
||||
[propKey]: true
|
||||
}
|
||||
}>()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user