LoginSignup
0
0

More than 3 years have passed since last update.

要素数が変わる object 定義をワンライナーで[Typescript]

Last updated at Posted at 2020-06-30

やりたいこと

type PossiblyUndefined = { possiblyUndefinedId?: number };

こんな感じのオブジェクトから possiblyUndefindId を取り出して、
そして required な name をくっつけて

type User =
  | {
      id: number;
      name: string;
    }
  | {
      name: string;
    };

こういったオブジェクトを作りたい。

普通にやると

こんな感じになるかなと。

const createUser = (
  name: string,
  possiblyUndefined?: PossiblyUndefined,
): User => {
  if (typeof possiblyUndefined?.possiblyUndefinedId === 'number')
    return {
      name,
      id: possiblyUndefined.possiblyUndefinedId,
    };
  return {
    name,
  };
};

ワンライナーで

スプレッド構文を使って、

const createUser = (
  name: string,
  possiblyUndefined?: PossiblyUndefined,
): User => ({
  name,
  ...(typeof possiblyUndefined?.possiblyUndefinedId === 'number' && {
    id: possiblyUndefined.possiblyUndefinedId,
  }),
});

シンプルなものも

it('simple spread', () => {
  const createUser = (n?: number): { id: number } | {} => ({
    ...(typeof n == 'number' && {
      id: n,
    }),
  });
  expect(createUser()).toStrictEqual({});
  expect(createUser(1000)).toStrictEqual({
    id: 1000,
  });
  expect(createUser(0)).toStrictEqual({
    id: 0,
  });
});

さいごに

スプレッド構文(... これ)を使うといろいろできて便利。

...(typeof possiblyUndefined?.possiblyUndefinedId === 'number' && {
  id: possiblyUndefined.possiblyUndefinedId,
}),

ここをいい感じにシュッとさせる方法があれば教えていただきたいです…

テスト全文

describe('spread test', () => {
  type PossiblyUndefined = {
    possiblyUndefinedId?: number;
  };
  type User =
    | {
        id: number;
        name: string;
      }
    | {
        name: string;
      };
  describe('normal', () => {
    const createUser = (
      name: string,
      possiblyUndefined?: PossiblyUndefined,
    ): User => {
      if (typeof possiblyUndefined?.possiblyUndefinedId === 'number')
        return {
          name,
          id: possiblyUndefined.possiblyUndefinedId,
        };
      return {
        name,
      };
    };
    it("'name', {possiblyUndefinedId: 1000}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: 1000,
      });
      expect(user).toStrictEqual({
        name: 'name',
        id: 1000,
      });
    });
    it("'name', {possiblyUndefinedId: -1000}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: -1000,
      });
      expect(user).toStrictEqual({
        name: 'name',
        id: -1000,
      });
    });
    it("'name', {possiblyUndefinedId: 0}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: 0,
      });
      expect(user).toStrictEqual({
        id: 0,
        name: 'name',
      });
    });
    it("'name', {possiblyUndefinedId: undefined}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: undefined,
      });
      expect(user).toStrictEqual({
        name: 'name',
      });
    });
    it("'name'", () => {
      const user = createUser('name');
      expect(user).toStrictEqual({
        name: 'name',
      });
    });
    it("'name', {}", () => {
      const user = createUser('name', {});
      expect(user).toStrictEqual({
        name: 'name',
      });
    });
  });
  describe('spread', () => {
    const createUser = (
      name: string,
      possiblyUndefined?: PossiblyUndefined,
    ): User => ({
      name,
      ...(typeof possiblyUndefined?.possiblyUndefinedId === 'number' && {
        id: possiblyUndefined.possiblyUndefinedId,
      }),
    });
    it("'name', {possiblyUndefinedId: 1000}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: 1000,
      });
      expect(user).toStrictEqual({
        name: 'name',
        id: 1000,
      });
    });
    it("'name', {possiblyUndefinedId: -1000}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: -1000,
      });
      expect(user).toStrictEqual({
        name: 'name',
        id: -1000,
      });
    });
    it("'name', {possiblyUndefinedId: 0}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: 0,
      });
      expect(user).toStrictEqual({
        id: 0,
        name: 'name',
      });
    });
    it("'name', {possiblyUndefinedId: undefined}", () => {
      const user = createUser('name', {
        possiblyUndefinedId: undefined,
      });
      expect(user).toStrictEqual({
        name: 'name',
      });
    });
    it("'name'", () => {
      const user = createUser('name');
      expect(user).toStrictEqual({
        name: 'name',
      });
    });
    it("'name', {}", () => {
      const user = createUser('name', {});
      expect(user).toStrictEqual({
        name: 'name',
      });
    });
  });
  it('simple spread', () => {
    const createUser = (n?: number): { id: number } | {} => ({
      ...(typeof n == 'number' && {
        id: n,
      }),
    });
    expect(createUser()).toStrictEqual({});
    expect(createUser(1000)).toStrictEqual({
      id: 1000,
    });
    expect(createUser(0)).toStrictEqual({
      id: 0,
    });
  });
});

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0