Comments (2)
I think I narrowed down the main (two) issue(s).
type Validating<T extends Types = Types> = {
type: T;
value: T extends Types.One ? string : never;
};
const Validating: Describe<Validating> = object({
type: enums(Object.values(Types)),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: dynamic((_, ctx): any => {
const type: Types = ctx.branch.at(-2)?.type ?? Types.One;
if (type === Types.One) {
return string();
} else {
return literal(undefined);
}
}),
});
This works, but requires you to set any
on the return type of the dynamic.
The second issue is when you make the value an array
of string
s, not a string
.
type Validating<T extends Types = Types> = {
type: T;
value: T extends Types.One ? string[] : never;
};
const Validating: Describe<Validating> = object({
type: enums(Object.values(Types)),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: dynamic((_, ctx): any => {
const type: Types = ctx.branch.at(-2)?.type ?? Types.One;
if (type === Types.One) {
return array(string());
} else {
return literal(undefined);
}
}),
});
This Gives you a cryptic type error, but this can be fixed by manually overriding the value type in the object like so:
const Validating: Describe<Validating> = object({
type: enums(Object.values(Types)),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: dynamic((_, ctx): any => {
const type: Types = ctx.branch.at(-2)?.type ?? Types.One;
if (type === Types.One) {
return array(string());
} else {
return literal(undefined);
}
}) as unknown as Describe<Validating["value"]>,
});
Still don't really have a nice fix for this, but hopefully this helps someone else facing the same issue.
from superstruct.
Could use Discriminated Union instead
export function discriminatorMapping<
D extends string,
Mapping extends Record<string, TypeAny>
>(
discriminator: D,
mapping: Mapping
): Struct<Simplify<DiscriminatedUnion<D, Mapping>>, null> {
return dynamic<any>((v: any = {}) => {
const discriminatorValue = (v as any)[discriminator];
const matched = mapping[discriminatorValue];
if (typeof (v as any)[discriminator] === "undefined" || !matched) {
return object({
[discriminator]: enums(Object.keys(mapping))
});
}
return object({
[discriminator]: literal(discriminatorValue),
...matched.schema
});
});
}
type DiscriminatedUnion<
D extends string,
Mapping extends Record<string, TypeAny>
> = ValueOf<{
[K in keyof Mapping]: { [k in D]: K } & Infer<Mapping[K]>;
}>;
type ValueOf<T> = T[keyof T];
enum NetType {
AIRGAP = "AIRGAP",
DIRECT = "DIRECT",
}
const t: Struct<{ netType: NetType.AIRGAP } | { netType: NetType.DIRECT, endpoint: string }> = discriminatorMapping("netType", {
[NetType.AIRGAP]: object(),
[NetType.DIRECT]: object({
endpoint: string()
})
}
)
from superstruct.
Related Issues (20)
- `instance` causes a TypeScript error with abstract classes HOT 1
- Unions of instances produce unhelpful error message
- Fix compatibility with Node16/NodeNext moduleResolution HOT 6
- Mask fails on `interface aaa { foo: string; [key: string]: any }` interface with any key.
- Move tests to Vitest
- Describe does not work well with union types HOT 2
- Does "create" supports "passthrough" HOT 2
- How can I generate declaration file from superstruct HOT 4
- Intersection of type schema and record with enums as keys HOT 1
- [Docs] Document pass-by-reference pitfall for `defaulted` values HOT 2
- Defaulted values are not correctly copied for `record` type data. HOT 6
- Create predefined JS object from Schema HOT 5
- `Describe` incorrectly handles single literal types. HOT 1
- Simplify testing suite with Vitest
- Add tests that check that all structs that work with non-primitive values copy their data during coercion
- What does a required value mean? HOT 2
- mask does not work anymore. HOT 2
- Feature Request: Add depth Option to partial for Nested Optional Attributes
- Unexpected interactions between refined structs and coerced structs
- Coercing a refined struct doesn't trigger refinement
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from superstruct.