Skip to content

Commit

Permalink
Tag values with their types to prevent clobbering
Browse files Browse the repository at this point in the history
Stringifying isn't good enough, because then a string and a number with
the same string value would be considered equal. Also, stringifying
Dates loses precision, so for those we need to use their internal
values.
  • Loading branch information
jacobmischka committed Jul 20, 2022
1 parent 76d52c3 commit c732603
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
19 changes: 16 additions & 3 deletions src/components/selectMultiple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,30 @@ export default function selectMultiple(logger: Logger) {
}
}

function getComparisonValue(value: z.infer<typeof primitiveValue>) {
if (value instanceof Date) {
return `date:${value.valueOf()}`
}

return `${typeof value}:${value}`
}

const normalizedOptions: z.infer<typeof labelValue>[] = props.options.map(
option => normalizeOption(option)
)
type Options = typeof props.options
const optionMap = new Map(
normalizedOptions.map((o, i) => [o.value.toString(), props.options[i]])
normalizedOptions.map((o, i) => [
getComparisonValue(o.value),
props.options[i],
])
)

let defaultValue = props.defaultValue?.map(d => normalizeOption(d))

if (
defaultValue &&
defaultValue.every(val => !optionMap.has(val.value.toString()))
defaultValue.every(val => !optionMap.has(getComparisonValue(val.value)))
) {
logger.warn(
'The defaultValue property must be a subset of the provided options, the provided defaultValue will be discarded.'
Expand All @@ -65,7 +76,9 @@ export default function selectMultiple(logger: Logger) {
options: normalizedOptions.map(o => stripper.parse(o)),
},
getValue(response: T_IO_RETURNS<'SELECT_MULTIPLE'>): Options {
return response.map(r => optionMap.get(r.value.toString())) as Options
return response.map(r =>
optionMap.get(getComparisonValue(r.value))
) as Options
},
}
}
Expand Down
20 changes: 17 additions & 3 deletions src/components/selectSingle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,35 @@ export default function selectSingle(logger: Logger) {
}
}

function getComparisonValue(value: z.infer<typeof primitiveValue>) {
if (value instanceof Date) {
return `date:${value.valueOf()}`
}

return `${typeof value}:${value}`
}

const normalizedOptions = props.options.map(option =>
normalizeOption(option)
)

type Options = typeof props.options
const optionMap = new Map(
normalizedOptions.map((o, i) => [o.value.toString(), props.options[i]])
normalizedOptions.map((o, i) => [
getComparisonValue(o.value),
props.options[i],
])
)
const stripper = richSelectOption.strip()

let defaultValue = props.defaultValue
? normalizeOption(props.defaultValue)
: undefined

if (defaultValue && !optionMap.has(defaultValue.value.toString())) {
if (
defaultValue &&
!optionMap.has(getComparisonValue(defaultValue.value))
) {
logger.warn(
'The defaultValue property must be a value in the provided options, the provided defaultValue will be discarded.'
)
Expand All @@ -68,7 +82,7 @@ export default function selectSingle(logger: Logger) {
options: normalizedOptions.map(o => stripper.parse(o)),
},
getValue(response: T_IO_RETURNS<'SELECT_SINGLE'>) {
return optionMap.get(response.value.toString()) as Options[0]
return optionMap.get(getComparisonValue(response.value)) as Options[0]
},
}
}
Expand Down

0 comments on commit c732603

Please sign in to comment.