skip to Main Content

I am trying to find the syntax to declare a type that has at least these properties, for example:

interface InspectedError {
  originalErrorObj: any,
  errorAsString: string,
  errorObjParsed: {
    message: string,
    stack: string
  }
}

the errorObjParsed value might have more properties, should I do this:

interface InspectedError {
  originalErrorObj: any,
  errorAsString: string,
  errorObjParsed: {
    message: string,
    stack: string,
    ...any
  }
}

there is the Partial<> construct, I am looking for like Subset<> or Superset<> construct, like this:

interface InspectedError {
  originalErrorObj: any,
  errorAsString: string,
  errorObjParsed: SupersetOf<{
    message: string,
    stack: string,
  }>
}

so that I could do:

const e = new Error('test');
e.foo = 'bar';

const v: InspectedError = {
   originalErrorObj: e,
   errorAsString: util.inspect(e),
   errorObjectParsed: {
      message: e.message,
      stack: e.stack,
      ...e
   }
}

and allow for any other arbitrary properties that might exist on e.

2

Answers


  1. There are various ways of achieving this, but assuming you want to avoid one involving classes and subclasses, I’d suggest:

    interface InspectedError {
      originalErrorObj: Error
      errorAsString: string
      errorObjParsed: {
        message: string
        stack: string
        [x: string]: any
      }
    }
    
    Login or Signup to reply.
  2. You could create the SuperSet<> construct you asked for using an index signature like this. This tells TypeScript to assume that errorObjParsed could have any properties besides message and stack. The only problem is that accessing properties that don’t actually exist on some hypothetical e will not give an error, and you won’t get code completion for anything besides message and stack.

    type SuperSet<T extends {}> = T & {[key: string]: any};
    
    interface InspectedError {
      originalErrorObj: any,
      errorAsString: string,
      errorObjParsed: SuperSet<{
        message: string,
        stack: string
      }>
    }
    

    Alternatively

    If you make InspectedError a generic type, then you can make errorObjParsed an intersection type. With this, you can safely access message, stack, and the properties of e.

    interface InspectedError<T extends {} = {}> {
      originalErrorObj: any,
      errorAsString: string,
      errorObjParsed: T & {
        message: string,
        stack: string
      }
    }
    
    const v: InspectedError<typeof e> = {
       originalErrorObj: e,
       errorAsString: 'asd',
       errorObjParsed: {
          message: e.message,
          stack: e.stack,
          ...e
       }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search