Rune Darkfire
Rune Darkfire4mo ago

Can't correctly type fields from a table to my NextTS application

This is more of a pure TS question than Convex, but at least it originates from the types of one of my convex function definitions. I'm getting this type error when trying to build my project (been fixing them by the dozens as we get ready for deployment) :
Type error: Type 'ReactMutation<FunctionReference<"mutation", "public", { id: Id<"documents">; orgId: string | null; storageId: Id<"_storage">; }, null, string | undefined>>' is not assignable to type '(params: { id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>; orgId?: string | null | undefined; storageId?: string | undefined; }) => Promise<...>'.
Types of parameters 'args' and 'params' are incompatible.
Type '{ id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>; orgId?: string | null | undefined; storageId?: string | undefined; }' is not assignable to type '{ id: Id<"documents">; orgId: string | null; storageId: Id<"_storage">; }'.
Types of property 'id' are incompatible.
Type 'XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>' is not assignable to type 'Id<"documents">'.
Type '{ [x: string]: undefined; [x: symbol]: undefined; readonly [x: number]: string; toString: () => string; charAt: (pos: number) => string; charCodeAt: (index: number) => number; concat: (...strings: string[]) => string; ... 48 more ...; __tableName: "documents"; }' is not assignable to type 'Id<"documents">'.
Type '{ [x: string]: undefined; [x: symbol]: undefined; readonly [x: number]: string; toString: () => string; charAt: (pos: number) => string; charCodeAt: (index: number) => number; concat: (...strings: string[]) => string; ... 48 more ...; __tableName: "documents"; }' is not assignable to type 'string'.
Type error: Type 'ReactMutation<FunctionReference<"mutation", "public", { id: Id<"documents">; orgId: string | null; storageId: Id<"_storage">; }, null, string | undefined>>' is not assignable to type '(params: { id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>; orgId?: string | null | undefined; storageId?: string | undefined; }) => Promise<...>'.
Types of parameters 'args' and 'params' are incompatible.
Type '{ id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>; orgId?: string | null | undefined; storageId?: string | undefined; }' is not assignable to type '{ id: Id<"documents">; orgId: string | null; storageId: Id<"_storage">; }'.
Types of property 'id' are incompatible.
Type 'XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>' is not assignable to type 'Id<"documents">'.
Type '{ [x: string]: undefined; [x: symbol]: undefined; readonly [x: number]: string; toString: () => string; charAt: (pos: number) => string; charCodeAt: (index: number) => number; concat: (...strings: string[]) => string; ... 48 more ...; __tableName: "documents"; }' is not assignable to type 'Id<"documents">'.
Type '{ [x: string]: undefined; [x: symbol]: undefined; readonly [x: number]: string; toString: () => string; charAt: (pos: number) => string; charCodeAt: (index: number) => number; concat: (...strings: string[]) => string; ... 48 more ...; __tableName: "documents"; }' is not assignable to type 'string'.
Now obviously that is a huge mouthful.
8 Replies
Convex Bot
Convex Bot4mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
Rune Darkfire
Rune DarkfireOP4mo ago
It's coming from this definition :
export const remove = mutation({
args: {
id: v.id("documents"),
storageId: v.id("_storage"),
orgId: v.union(v.string(), v.null())
}, ...
export const remove = mutation({
args: {
id: v.id("documents"),
storageId: v.id("_storage"),
orgId: v.union(v.string(), v.null())
}, ...
being read by this :
const deleteDocument = useMutation(api.documents.remove)
const deleteDocument = useMutation(api.documents.remove)
being fed into this component :
<DeleteDialog
resourceType="document"
deleteFunction={deleteDocument}
resource={doc}
/>
<DeleteDialog
resourceType="document"
deleteFunction={deleteDocument}
resource={doc}
/>
. DeleteDialog has the following interface & declaration that I've been muddling through :
interface DeleteDialogProps {
resourceType: string;
deleteFunction: (params:
{ id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>;
orgId?: string | null;
storageId?: string }) => Promise<void>;
resource: { _id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>;
storageId?: string };
isDetailsScreen?: boolean;
hasAttachedResources: (id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>) => boolean;
}

export function DeleteDialog({
resourceType,
deleteFunction,
resource,
isDetailsScreen = false,
hasAttachedResources = () => false,
}: DeleteDialogProps) { ...
interface DeleteDialogProps {
resourceType: string;
deleteFunction: (params:
{ id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>;
orgId?: string | null;
storageId?: string }) => Promise<void>;
resource: { _id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>;
storageId?: string };
isDetailsScreen?: boolean;
hasAttachedResources: (id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>) => boolean;
}

export function DeleteDialog({
resourceType,
deleteFunction,
resource,
isDetailsScreen = false,
hasAttachedResources = () => false,
}: DeleteDialogProps) { ...
. I feel like I researched & put in all these XORs for nothing and I'm still getting the same result. Any help at all would be appreciated - thank you! The XORs are from a package called ts-essentials FWIW - this code all works/worked perfectly in our development environment (before I went crazy with all this typing)
jamalsoueidan
jamalsoueidan4mo ago
//REPLACE
orgId: v.union(v.string(), v.null())
// WITH
orgId: v.optional(v.string())
//REPLACE
orgId: v.union(v.string(), v.null())
// WITH
orgId: v.optional(v.string())
deleteFunction
//REPLACE
deleteFunction: (params:
{ id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>;
orgId?: string | null;
storageId?: string }) => Promise<void>;

// WITH
deleteFunction: FunctionReference<"mutation", "public", (typeof api.documents.remove)["_args"], null, string | undefined>
//REPLACE
deleteFunction: (params:
{ id: XOR<Id<"documents">, Id<"vendors">, Id<"contracts">, Id<"riskAssessments">>;
orgId?: string | null;
storageId?: string }) => Promise<void>;

// WITH
deleteFunction: FunctionReference<"mutation", "public", (typeof api.documents.remove)["_args"], null, string | undefined>
Rune Darkfire
Rune DarkfireOP4mo ago
@jamalsoueidan thanks for this, will try it out in the morning, appreciate the prompt response!
Rune Darkfire
Rune DarkfireOP4mo ago
@jamalsoueidan oh, I just realized... orgId can't be optional... it is always present, and sometimes it is null, because that's what's needed for clerk I suppose I could rework the concept of orgId but that would be a pretty big change to the application as a whole
jamalsoueidan
jamalsoueidan4mo ago
Your code might be tightly coupled that's why big change,,,
Rune Darkfire
Rune DarkfireOP4mo ago
@jamalsoueidan now I'm just getting a different build error instead :
Type error: This expression is not callable.
Type 'FunctionReference<"mutation", "public", { orgId?: string | undefined; id: Id<"documents">; storageId: Id<"_storage">; }, null, string | undefined>' has no call signatures.
Type error: This expression is not callable.
Type 'FunctionReference<"mutation", "public", { orgId?: string | undefined; id: Id<"documents">; storageId: Id<"_storage">; }, null, string | undefined>' has no call signatures.
from my call of the function :
await deleteFunction({
id: resource._id,
orgId: orgId,
... resourceType === 'document' && { storageId: resource.storageId },
})
await deleteFunction({
id: resource._id,
orgId: orgId,
... resourceType === 'document' && { storageId: resource.storageId },
})

Did you find this page helpful?