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

# やりたいこと

```ts
type PossiblyUndefined = { possiblyUndefinedId?: number };
```

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

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

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


# 普通にやると

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

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

# ワンライナーで

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

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

## シンプルなものも

```ts
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,
  });
});
```

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


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

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

# テスト全文

```ts
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,
    });
  });
});

```