Closed jojojojojoj5564656465465 closed 3 weeks ago
// In types.ts, let's first add some utility types
/**
* Utility type to extract discriminator value
*/
type ExtractDiscriminatorValue<T> = T extends { [K in any]: infer U } ? U : never;
/**
* Utility type to get the object corresponding to a discriminator value
*/
type ExtractVariantType<T, K extends string, V> = T extends { [key in K]: V } ? T : never;
/**
* Modified VariantSchema to support discriminated type inference
*/
export interface VariantSchema<
TKey extends string,
TOptions extends VariantOptions<TKey>,
TMessage extends ErrorMessage<VariantIssue> | undefined,
> extends BaseSchema<
InferInput<TOptions[number]>,
| InferOutput<TOptions[number]>,
VariantIssue | InferVariantIssue<TOptions>
> {
readonly type: 'variant';
readonly reference: typeof variant;
readonly expects: 'Object';
readonly key: TKey;
readonly options: TOptions;
readonly message: TMessage;
// Add discriminated type for inference
readonly _variantBrand: {
[K in TKey]: {
[V in ExtractDiscriminatorValue<InferOutput<TOptions[number]>[TKey]>]:
ExtractVariantType<InferOutput<TOptions[number]>, TKey, V>
}
};
}
/**
* Modified parse function to support discriminated type inference
*/
export function parse<T extends BaseSchema<any, any, any>>(
schema: T,
input: unknown
): T extends VariantSchema<infer K, any, any>
? T['_variantBrand'][K][keyof T['_variantBrand'][K]]
: InferOutput<T> {
// ... rest of implementation
}
/**
* Modified variant function to use the new types
*/
export function variant<
const TKey extends string,
const TOptions extends VariantOptions<TKey>,
>(key: TKey, options: TOptions): VariantSchema<TKey, TOptions, undefined>;
export function variant<
const TKey extends string,
const TOptions extends VariantOptions<TKey>,
const TMessage extends ErrorMessage<VariantIssue> | undefined,
>(
key: TKey,
options: TOptions,
message: TMessage
): VariantSchema<TKey, TOptions, TMessage>;
export function variant(
key: string,
options: VariantOptions<string>,
message?: ErrorMessage<VariantIssue>
): VariantSchema<string, VariantOptions<string>, ErrorMessage<VariantIssue> | undefined> {
return {
kind: 'schema',
type: 'variant',
reference: variant,
expects: 'Object',
async: false,
key,
options,
message,
'~standard': 1,
'~vendor': 'valibot',
_variantBrand: {} as any, // Type safety is handled by the type system
'~validate'(dataset, config = getGlobalConfig()) {
// ... rest of existing implementation
},
};
}
This is the default behaviour of TypeScript and not related to Valibot. Learn more about discriminated unions in the TypeScript docs: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions
https://valibot.dev/playground/?code=JYWwDg9gTgLgBAKjgQwM5wG5wGZQiOAcg2QBtgAjCGQgbgCh6BjCAO1XgDVkphlWYAZSYALAKYhkcALyYAdCV78YACkIwAnmDGEANHADa9OPIgUAVmKaqA3sZNxN2gFzzyMMVDJqJyYKUIASl17E19-Vww5MGBtFSiOXlYAcxVg+XDSNODQuFZkEDFnBJgk1MD7AF8ckyizS2sVOwdHLSK3YA8vLMIAVygAmod+0kjo2LF4uUTgFLT9KJHskJNqldMLK1tcp3ao909vQgATZA8g9ZNTjzGYuJKy+flgVAgAETPJwKG1+gBdQIMei7ODcJQCAAqbRk8gAkqxsJ54WBejAADy7CDYUE8PgCYTiSQAPiBjBY7HgUDEqF6pBgzjBeJgUO0MKiYB4qEmjOUBN8+macEyrkI5n4YgAAmIAB4FMCkMRyFggPT2XYizKq6pwRjMNgcOD1GGC4VEMWsSUyuUKpX4VUmdVETUhSr0Kk0ulyTL0epeyT+IA