I recently started experimenting with the enum-based nominal typing technique explained in more detail at this link.
enum PersonIdBrand {}
export type PersonId = PersonIdBrand & string
interface Person {
id: PersonId
firstName: string
lastName: string
}
During my testing, I encountered an issue while adding types to certain factory methods utilized in tests. These utility functions facilitate the creation of test data with default values that can be overridden selectively:
const makeTestPerson = ({
id = 'personId' as PersonId,
firstName = 'Bob',
lastName = 'Smith'
}: Partial<Person> = {}): Person => ({
id,
firstName,
lastName
})
const person = makeTestPerson({ lastName: 'Ross' })
However, when using tsc
, an error occurs:
error TS2322: Type 'PersonId' is not assignable to type 'never'.
11 id = 'personId' as PersonId,
If I switch to using id: string
instead, it compiles without any issues. Is there a way to ensure these functions pass type checking with PersonId
?
Update: After further exploration, I believe there might be a more underlying problem with this approach:
const maybePersonId: PersonId | undefined = ("personId" as PersonId)
This also results in a failure message:
TS2322: Type 'PersonId' is not assignable to type 'undefined'.
But why does this fail? Shouldn't an X
always be able to be assigned to X | undefined
?