1

I'm trying to make something typesafe and I'm not 100% sure if it's possible:

If I have an array of "services", where a Service is defined as:

interface Service {
  id: string;
  dependencies?: [string] // refs to others Service.id's
}

Is there a way to make the dependencies array typesafe? To illustrate:

import { Service } from './service.ts';

const services: Service[] = [
  {
    id: "authors",
  },
  {
    id: "comments",
  }
  {
    id: "posts",
    dependencies: [] // <-- type this as `Array<"authors | "comments">`
  }
]
1
  • You can declare dependencies as an array of enums. Just extract ids to separate enum. If you need unique values in the array then declare it as Set. Commented Oct 24, 2020 at 8:31

2 Answers 2

2

You can use unions to do something like this:

type RawType = "authors" | "comments";
type RawId = { id : RawType };
type Posts = {
  id: "posts";
  dependencies: RawType[];
}

type Service = RawId | Posts;

// then you can declare an array of Service
const services: Service[] = [
  {
    id: "authors",
  },
  {
    id: "comments",
  },
  {
    id: "posts",
    dependencies: [],
  }
];

Playground

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

Comments

0

A little bit ugly - to ensure that the id is listed in the array of the dependnecies, you can do the following:

type Id = 'id1' | 'id2' | 'id3'
type Obj<CurrentId extends Id> = {
  id: CurrentId
  dependencies: Exclude<Id, CurrentId>[]
}

const obj: <CurrentId extends Id>(obj: Obj<CurrentId>) => Obj<CurrentId> = obj => obj

const array = [
  obj({
    id: 'id1',
    dependencies: [], // compiled
  }),
  obj({
    id: 'id2',
    dependencies: ['id1'], // compiled
  }),
  obj({
    id: 'id3',
    dependencies: ['id3'], // compilation error
  }),
  obj({
    id: 'id3', // note: compiled even when there are multiple objects with the same Id
    dependencies: [],
  }),
]

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.