|
|
@@ -174,12 +174,10 @@ export type ExtractDefaultPropTypes<O> = O extends object
|
|
|
{ [K in keyof Pick<O, DefaultKeys<O>>]: InferPropType<O[K]> }
|
|
|
: {}
|
|
|
|
|
|
-type NormalizedProp =
|
|
|
- | null
|
|
|
- | (PropOptions & {
|
|
|
- [BooleanFlags.shouldCast]?: boolean
|
|
|
- [BooleanFlags.shouldCastTrue]?: boolean
|
|
|
- })
|
|
|
+type NormalizedProp = PropOptions & {
|
|
|
+ [BooleanFlags.shouldCast]?: boolean
|
|
|
+ [BooleanFlags.shouldCastTrue]?: boolean
|
|
|
+}
|
|
|
|
|
|
// normalized value is a tuple of the actual normalized options
|
|
|
// and an array of prop keys that need value casting (booleans and defaults)
|
|
|
@@ -564,16 +562,36 @@ export function normalizePropsOptions(
|
|
|
const opt = raw[key]
|
|
|
const prop: NormalizedProp = (normalized[normalizedKey] =
|
|
|
isArray(opt) || isFunction(opt) ? { type: opt } : extend({}, opt))
|
|
|
- if (prop) {
|
|
|
- const booleanIndex = getTypeIndex(Boolean, prop.type)
|
|
|
- const stringIndex = getTypeIndex(String, prop.type)
|
|
|
- prop[BooleanFlags.shouldCast] = booleanIndex > -1
|
|
|
- prop[BooleanFlags.shouldCastTrue] =
|
|
|
- stringIndex < 0 || booleanIndex < stringIndex
|
|
|
- // if the prop needs boolean casting or default value
|
|
|
- if (booleanIndex > -1 || hasOwn(prop, 'default')) {
|
|
|
- needCastKeys.push(normalizedKey)
|
|
|
+ const propType = prop.type
|
|
|
+ let shouldCast = false
|
|
|
+ let shouldCastTrue = true
|
|
|
+
|
|
|
+ if (isArray(propType)) {
|
|
|
+ for (let index = 0; index < propType.length; ++index) {
|
|
|
+ const type = propType[index]
|
|
|
+ const typeName = isFunction(type) && type.name
|
|
|
+
|
|
|
+ if (typeName === 'Boolean') {
|
|
|
+ shouldCast = true
|
|
|
+ break
|
|
|
+ } else if (typeName === 'String') {
|
|
|
+ // If we find `String` before `Boolean`, e.g. `[String, Boolean]`,
|
|
|
+ // we need to handle the casting slightly differently. Props
|
|
|
+ // passed as `<Comp checked="">` or `<Comp checked="checked">`
|
|
|
+ // will either be treated as strings or converted to a boolean
|
|
|
+ // `true`, depending on the order of the types.
|
|
|
+ shouldCastTrue = false
|
|
|
+ }
|
|
|
}
|
|
|
+ } else {
|
|
|
+ shouldCast = isFunction(propType) && propType.name === 'Boolean'
|
|
|
+ }
|
|
|
+
|
|
|
+ prop[BooleanFlags.shouldCast] = shouldCast
|
|
|
+ prop[BooleanFlags.shouldCastTrue] = shouldCastTrue
|
|
|
+ // if the prop needs boolean casting or default value
|
|
|
+ if (shouldCast || hasOwn(prop, 'default')) {
|
|
|
+ needCastKeys.push(normalizedKey)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -595,6 +613,7 @@ function validatePropName(key: string) {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
+// dev only
|
|
|
// use function string name to check type constructors
|
|
|
// so that it works across vms / iframes.
|
|
|
function getType(ctor: Prop<any>): string {
|
|
|
@@ -617,22 +636,6 @@ function getType(ctor: Prop<any>): string {
|
|
|
return ''
|
|
|
}
|
|
|
|
|
|
-function isSameType(a: Prop<any>, b: Prop<any>): boolean {
|
|
|
- return getType(a) === getType(b)
|
|
|
-}
|
|
|
-
|
|
|
-function getTypeIndex(
|
|
|
- type: Prop<any>,
|
|
|
- expectedTypes: PropType<any> | void | null | true,
|
|
|
-): number {
|
|
|
- if (isArray(expectedTypes)) {
|
|
|
- return expectedTypes.findIndex(t => isSameType(t, type))
|
|
|
- } else if (isFunction(expectedTypes)) {
|
|
|
- return isSameType(expectedTypes, type) ? 0 : -1
|
|
|
- }
|
|
|
- return -1
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* dev only
|
|
|
*/
|