Closed bradymwilliams closed 1 year ago
I'll shoot from the hip here about what I think is going on. When it's inline in the s.document
, it's typing things as literals more often than not, so the generics can pull out the actual fields. fields
isn't just an array of arbitrary fields, it's an array with name: 'foo'
with type: 'string'
, etc.
When you pulled it out into shared_fields
, I'm assuming it's not of type { name: 'name', ...}[]
but actually { name: string, ... }[]
. When s.document
gets that, it's unclear what to do. It'll be an object where the fields' names are strings, not specific strings. How would it know what the fields' names are or of what type? Try throwing in some as const
on things that could get "generalized". For example, the name: 'name' as const
. Does that change things?
If that's the issue, it would be nice to have some kind of exported type from this library you could use to make this a little easier. Until then, make sure the types of your shared_fields
don't end up broader than is helpful. The moment it's something along the lines of { name: string; type: any }[]
, you're not actually restricting anything.
I haven't checked out your issue at all to see if this is the case.
Thanks for response 🙏 as const
doesn't seem to affect anything. I'm already over my skis some here but something worth mentioning is I first reached for an s.field
for the shared_fields
items similar to sanity's defineField()
experience.
Yeah, so s.document
uses generics with fields
and those generics get auto-magically derived to a narrower type when you throw fields directly in, so it can give you a document with the correct shape. When it's in an external array like that, the array becomes a much broader type so, even if it didn't error, wouldn't give you the shape you wanted anyways.
Something like this would work, just so it ends up inferring the same type that document would:
const sharedFields = <
Names extends string,
Zods extends z.ZodTypeAny,
ResolvedValues,
Optionals extends boolean,
FieldsArray extends TupleOfLength<
FieldOptions<Names, Zods, ResolvedValues, Optionals>,
1
>
>(
fields: FieldsArray
) => fields;
const fields = sharedFields([
{
name: "foo",
type: boolean(),
},
{
name: "bar",
optional: true,
type: string(),
},
]);
const type = document({
name: "foo",
fields,
});
Something I could export from the package, just haven't yet.
I have a few places in my codebase where I'm defining shared fields in an array to map over and alter in the document definitions. When I reference those shared fields in the document definition I get the following type error:
`Type '{ name: string; type: SanityType<{ options: (Omit<StringOptions | undefined, "list"> & { list?: [string | { title: string; value: string; }, ...(string | { title: string; value: string; })[]] | undefined; }) | undefined; ... 6 more ...; placeholder?: string | undefined; }, string, string, string>; }[]' is not assignable to type '[FieldOptions<string, ZodTypeAny, unknown, boolean>, ...FieldOptions<string, ZodTypeAny, unknown, boolean>[]]'.
Source provides no match for required element at position 0 in target.`
Weird thing is if I access a shared field by index on the array no typeerror shows so its only iteration that makes this throw. I even tried exporting the FieldsArray type from but that type requires arguments I'm not sure how to make dynamic. Any help/feedback appreciated.