0

Consider the following type:

type UserList = {
  userIds: string[]
  userData: {
    [UserId in UserList['userIds'][number]]: {
      userId: UserId
      username: string
    }
  }
}

with that I want to tell TypeScript compiler two things:

  1. userData keys must exist in userIds
  2. userId field must be equal to the key of the same entry

I feel that I need some kind of this or self keyword instead of UserList

1 Answer 1

0

I don't believe it's possible to refer to the exact string values inside userIds without resorting to using a generic type parameter:

type UserList<T extends ReadonlyArray<string>> = {
  userIds: T
  userData: {
    [UserId in T[number]]: {
      userId: UserId
      username: string
    }
  }
}

And your type definition would have to look as follows:

const a: UserList<['hello']> = {
    userIds: ['hello'],
    userData: {
        hello: {
            userId: 'hello',
            username: 'username'
        }
    }
}

If you don't want to specify the user IDs twice (inside the generic parameter and inside the actual UserList variable), you have to use a wrapper function:

function asUserList<T extends ReadonlyArray<string>>(list: UserList<T>) {
  return list;
}

const a = asUserList({
    userIds: ['hello'] as const,
    userData: {
        hello: {
            userId: 'hello',
            username: 'username'
        }
    }
})

If you don't use a generic parameter and instead try to use the this type inside an interface like this:

interface UserList {
  userIds: string[]
  userData: {
    [UserId in this['userIds'][number]]: {
      userId: UserId
      username: string
    }
  }
}

It wouldn't work because this['userIds'] would always resolve to the weak string[] type, not a specific set of strings that would allow you to strongly type userData based on the exact value of userIds.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.