#discriminated union from enum

24 messages · Page 1 of 1 (latest)

upbeat bear
#

Hi there,

I'm trying to create an error object for PostgresErrors, and want to have type safety whenever I add a new property.

I have an enum containing all of thePostgres errors, where the key is the error_condition and the value is the error_code, E.G:
UNIQUE_VIOLATION = '23505'

Then I want to have an object/map where the key is the error_code, and the value contains details about that error_code, including the responding error_condition. We already have the relation in the enum, but how can I discriminate this, so that I can only select 1 specific condition_error that relates to the error_code?


const postgresErrors: PostgresErrors = {
  '23505': {
    errorCondition: '' <- // this can only be 1 specific errorCondition, that relates to 23505
    description: 'Duplicate key value violates unique constraint',
    translationKey: 'errors.database_errors.unique_violation',
  },
};

#

here are the types that I have so far:


PostgresErrorEnum {
  UNIQUE_VIOLATION = '23505'
}


type PostgresErrorCondition = keyof typeof PostgresErrorEnum // literal union containing all error conditions
type PostgresErrorCode = `${PostgresErrorEnum}`; // literal union containing all error codes

interface PostgresDetailedError {
  errorCondition: PostgresErrorCondition;
  description: string;
  translationKey: TranslationKeys;
}

type PostgresErrors = Record<PostgresErrorCode, PostgresDetailedError>;

const postgresErrors: PostgresErrors = {
  '23505': {
    errorCondition: '',
    description: 'Duplicate key value violates unique constraint',
    translationKey: 'errors.database_errors.unique_violation',
  },
};

queen jasper
#

sorry if i missed this, but what part of that is the "condition_error"?

#

i'm pretty sure you need a mapped type, i'm just not sure what you want it to look like

#

!hb mapped type

ashen egretBOT
upbeat bear
#

sorry, my bad I had the properties misnamed in the 2nd example

queen jasper
#

do you mean that errorCondition would be like 'UNIQUE_VIOLATION', etc?

upbeat bear
#

it is essentially the property errorCondition (empty string in the example), that I want to be discriminated to UNIQUE_VIOLATION when the key is 23505

queen jasper
#

okay gotcha, gimme a minute

#

how's this?

ashen egretBOT
#
mkantor#0

Preview:```ts
type TranslationKeys = string

enum PostgresErrorEnum {
UNIQUE_VIOLATION = "23505",
}

type PostgresErrors = {
[K in keyof typeof PostgresErrorEnum as typeof PostgresErrorEnum[K]]: {
errorCondition: K
description: string
translationKey: TranslationKeys
...```

queen jasper
#

!ts PostgresErrors

ashen egretBOT
#
type PostgresErrors = {
    readonly 23505: {
        errorCondition: "UNIQUE_VIOLATION";
        description: string;
        translationKey: TranslationKeys;
    };
} /* 7:6, 15:23 */```
upbeat bear
#

damn, works like a charm!

#

I would have never gotten that myself, thank you so much

queen jasper
#

you're welcome

upbeat bear
#

sorry to bother you again, one last thing.

Currently it is forcing me to have the object contain every single instance from the enum in the object, which I don't want - I just want to be able to extend it when needed - how do I fix that?

queen jasper
#

you could slap a ? on the index of the mapped type too

#

[K in keyof typeof PostgresErrorEnum as typeof PostgresErrorEnum[K]]?: …

upbeat bear
#

aah ofc, makes sense

#

thank you again mate, I really appreciate that