1
interface Link {
    href: string;
}

type MandatoryPaginationLinks = {
    [key in 'first' | 'last']: Link;
}
type OptionalPaginationLinks = {
    [key in 'prev' | 'next']: Link | null;
}
type PaginationLinks = MandatoryPaginationLinks & OptionalPaginationLinks;

type AdditionalLinks = {
    [key: string]: Link;
};

type Links = PaginationLinks & AdditionalLinks;

const links: Links = {
    self: {
        href: 'asdf'
    },
    prev: null,
    next: {
        href: '',
    },
    first: {
        href: 'asdf'
    },
    last: {
        href: 'asdf'
    }
};

I have a Links type. first and last properties have to be set and must be Link. prev and next properties can be whether a Link or null. Optional links must have Link type. The problem is that Typescript sees 'first', 'last', 'prev' and 'next' as string so the expression is always mapped to AdditionalLinks type. I want to have a solution to exclude these four strings from string type. For example (not working):

type AdditionalLinks = {
    [key: Omit<string, 'first' | 'last' | 'prev' | 'next'>]: Link;
};
Usitha Indeewara
  • 870
  • 3
  • 10
  • 21
PeterFox
  • 43
  • 2
  • 1
    There is no specific type in TypeScript that works this way, unfortunately. You're looking for something like a [rest index signature as suggested in ms/TS#17867](https://github.com/microsoft/TypeScript/issues/17867) or possibly negated types, neither of which TS supports. `Omit` doesn't mean what you want it to mean (`Omit` would remove *keys* of `string` like `"toUpperCase"`); you maybe mean `Exclude`, but `Exclude` only removes from unions, and `string` is not a union. – jcalz Oct 15 '22 at 20:17
  • The various workarounds I know of are listed in the answer to [the linked question](https://stackoverflow.com/questions/61431397/how-to-define-typescript-type-as-a-dictionary-of-strings-but-with-one-numeric-i) – jcalz Oct 15 '22 at 20:18

1 Answers1

0

I don't think what you want is possible. But as an alternative solution you can use symbol instead of the string keys in AdditionalLinks. So that ‍‍first, last, prev, next do not interfere with AdditionalLinks symbol keys.

type AdditionalLinks = {
    [key: symbol]: Link;
};

Next you can define links like this:

const links: Links = {
    [test]: {
        href: 'asdf'
    },
    prev: null,
    next: {
        href: '',
    },
    first: {
        href: 'asdf'
    },
    last: {
        href: 'asdf'
    }
};

You can declare a symbol:

const test = Symbol('test');

And for example you can get a symbol typed key's value like this:

links[test]
mahooresorkh
  • 1,361
  • 2
  • 8
  • 16