TypeScript error: Type 'string' is not assignable to union value

Hello friends. I've picked up my side project again this week and I'm trying to add a new feature (required field indicator). It's a component library for forms. It's expecting specific form data:
export interface Form {
databaseId: number
... extra stuff ...
customRequiredIndicator?: string | null
requiredIndicator?: "TEXT" | "ASTERISK" | "CUSTOM" | null
submitButton: Button
formFields: { nodes: Field[] }
}
export interface Form {
databaseId: number
... extra stuff ...
customRequiredIndicator?: string | null
requiredIndicator?: "TEXT" | "ASTERISK" | "CUSTOM" | null
submitButton: Button
formFields: { nodes: Field[] }
}
When a user passes in the form data, they may or may not include the requiredIndicator. If they do, it can be either "TEXT", "ASTERISK", "CUSTOM" or a null value. I thought I could tell TypeScript that these are the only 3 string values that it could be and have it work. But when I actually test it out, I get the following error: Type 'string' is not assignable to type '"TEXT" | "ASTERISK" | "CUSTOM" | null | undefined'. I've tried a bunch of things and can't seem to sort it out. I think the issue is that because I have no control over the data that the user is passing into the <Form> component, I can't use a type assertion. I'm thinking that just typing it as 'string' is fine enough. I just thought that TypeScript could do this too. I could stand to learn more, so I'm open to anything y'all have for me. Thanks!
Solution:
Typescript infers the types from the json to be plain types like string, and so you can assert type for it to be proper. To do so you can do the following, where Form is the type you defined ```ts import data from "../data/query.json" const mockData = data as Form...
Jump to solution
7 Replies
shiroyasha9
shiroyasha914mo ago
It should work. How are you testing it? I mean, can you share the instance of where do you get that error?
mosesintech
mosesintech14mo ago
On this branch (feature/typesafe-v1). Running npm run start spins up the example app in example/src/app.tsx using data from example/data/query.json https://github.com/TotalityWorks/wpgravitybundle/blob/feature/typesafe-v1/example/src/app.tsx I get the error when I run start. Full error message:
[tsl] ERROR in /Users/maxcosme/Development/TotalityWorks/wpgravitybundle/example/src/app.tsx(82,18)
TS2322: Type '{ databaseId: number; cssClass: null; customRequiredIndicator: null; dateCreated: string; dateCreatedGmt: string; description: string; descriptionPlacement: string; firstPageCssClass: string; ... 18 more ...; formFields: { ...; }; }' is not assignable to type 'Form'.
Types of property 'requiredIndicator' are incompatible.
Type 'string' is not assignable to type '"TEXT" | "ASTERISK" | "CUSTOM" | null | undefined'.
ts-loader-default_e3b0c44298fc1c14

webpack 5.75.0 compiled with 1 error in 10476 ms
[tsl] ERROR in /Users/maxcosme/Development/TotalityWorks/wpgravitybundle/example/src/app.tsx(82,18)
TS2322: Type '{ databaseId: number; cssClass: null; customRequiredIndicator: null; dateCreated: string; dateCreatedGmt: string; description: string; descriptionPlacement: string; firstPageCssClass: string; ... 18 more ...; formFields: { ...; }; }' is not assignable to type 'Form'.
Types of property 'requiredIndicator' are incompatible.
Type 'string' is not assignable to type '"TEXT" | "ASTERISK" | "CUSTOM" | null | undefined'.
ts-loader-default_e3b0c44298fc1c14

webpack 5.75.0 compiled with 1 error in 10476 ms
GitHub
wpgravitybundle/example/src/app.tsx at feature/typesafe-v1 · Totali...
A component and a hook to simplify your headless WordPress React application using Gravity Forms. - TotalityWorks/wpgravitybundle
Solution
shiroyasha9
shiroyasha914mo ago
Typescript infers the types from the json to be plain types like string, and so you can assert type for it to be proper. To do so you can do the following, where Form is the type you defined
import data from "../data/query.json"
const mockData = data as Form
import data from "../data/query.json"
const mockData = data as Form
mosesintech
mosesintech14mo ago
You are exactly right. I took a look at how I was using the package in the wild and realized I was doing exactly that, so past me must have known something that present me forgot:
import { useStaticQuery, graphql } from "gatsby"

// import types
import type { Form } from "wpgravitybundle"

const useGravityData = () => {
const { allWpGfForm } = useStaticQuery(
graphql`
query FormQuery {
allWpGfForm {
nodes {
databaseId
formFields {
nodes {
databaseId
type
visibility
pageNumber
}
}
submitButton {
text
type
}
}
}
}
`
)
const allForms = allWpGfForm as { nodes: Form[] }
return { allForms }
}

export default useGravityData
import { useStaticQuery, graphql } from "gatsby"

// import types
import type { Form } from "wpgravitybundle"

const useGravityData = () => {
const { allWpGfForm } = useStaticQuery(
graphql`
query FormQuery {
allWpGfForm {
nodes {
databaseId
formFields {
nodes {
databaseId
type
visibility
pageNumber
}
}
submitButton {
text
type
}
}
}
}
`
)
const allForms = allWpGfForm as { nodes: Form[] }
return { allForms }
}

export default useGravityData
Thanks for the help @shiroyasha9. You're the best
shiroyasha9
shiroyasha914mo ago
Glad to be here 🤝🏼
mosesintech
mosesintech14mo ago
Actually @shiroyasha9, it fixed the compile issue I had but it isn't actually checking the type right. If I have requiredIndicator as "TEXTs", it still works. Shouldn't that cause an error?
shiroyasha9
shiroyasha914mo ago
Type assertion is your way of telling typescript to shut up and assume that the type will always be what you mention. Simply speaking, it is the equivalent of "trust me bro". We can do one of the following things here - 1. Add runtime validation check - use a library like zod where you define a schema (formSchema) and parse your data against that. It the data does not match schema, it throws an error which you can handle. 2. Convert the query.json file to a .ts file - This will help you define an object with the specified Form type.
export const data: Form[] = [{...}]
export const data: Form[] = [{...}]
This way typescript will properly check the values and show you an error if you have written a value incorrectly. The error will however not be shown at the place of usage, but rather where you define the data (query.ts) in this example.
Want results from more Discord servers?
Add your server