Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: invert 명확한 타입 추론을 위한 타입 개선 #219

Merged
merged 2 commits into from
Jun 13, 2024

Conversation

ssi02014
Copy link
Contributor

@ssi02014 ssi02014 commented Jun 12, 2024

Overview

invert가 조금 더 명확한 타입을 추론하기 위해 타입을 개선하였습니다.
이제 invert함수가 조금 더 명확한 타입을 추론할 수 있습니다.

Case1

// as-is
const obj = {
  a: { name: 'foo' },
  b: { name: 'bar' },
} as const;

const result = invert(obj, (value) => value.name);
// const result: Record<PropertyKey, any>
// to-be
const obj = {
  a: { name: 'foo' },
  b: { name: 'bar' },
} as const;

const result = invert(obj, (value) => value.name);
// const result: Record<'foo' | 'bar', 'a' | 'b'>

Case2

// as-is
const obj = { a: 1, b: 2, c: 3 };
const keyTransformer = (value: number): `key_${number}` => `key_${value}`;

const result = invert(obj, keyTransformer);
// const result: Record<PropertyKey, any>
// to-be
const obj = { a: 1, b: 2, c: 3 };
const keyTransformer = (value: number): `key_${number}` => `key_${value}`;

const result = invert(obj, keyTransformer);
// const result: Record<`key_${number}`, "a" | "b" | "c">

PR Checklist

  • All tests pass.
  • All type checks pass.
  • I have read the Contributing Guide document.
    Contributing Guide

@ssi02014 ssi02014 added @modern-kit/utils @modern-kit/utils fix 버그 수정 및 코드 개선 labels Jun 12, 2024
@ssi02014 ssi02014 requested a review from Sangminnn June 12, 2024 11:55
@ssi02014 ssi02014 self-assigned this Jun 12, 2024
Copy link

changeset-bot bot commented Jun 12, 2024

⚠️ No Changeset found

Latest commit: 72d8a13

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

codecov bot commented Jun 12, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.66%. Comparing base (b239f85) to head (72d8a13).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #219      +/-   ##
==========================================
+ Coverage   95.64%   95.66%   +0.01%     
==========================================
  Files          87       87              
  Lines         872      876       +4     
  Branches      203      203              
==========================================
+ Hits          834      838       +4     
  Misses         32       32              
  Partials        6        6              
Components Coverage Δ
@modern-kit/react 92.11% <ø> (ø)
@modern-kit/utils 100.00% <100.00%> (ø)

Comment on lines +7 to +13
export const invert = <
K extends PropertyKey,
V,
TK extends PropertyKey = V extends PropertyKey ? V : PropertyKey
>(
obj: Record<K, V>,
keyTransformer: (value: V) => TK = defaultKeyTransformer<V, TK>
Copy link
Contributor Author

@ssi02014 ssi02014 Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TK는 keyTransformer의 반환 타입입니다.

만약 V가 PropertyKey의 서브타입이면 TK는 V를 기본 타입으로 갖습니다.
반면에 V가 PropertyKey에 호환되지 않으면 TK는 PropertyKey를 기본 반환타입으로 갖습니다.

이를 통해 keyTransformer를 활용해 key가 변환 되더라도 더욱 명확한 타입 추론이 가능하며, keyTransformer가 참조형을 반환하지 않게 방지 할 수 있습니다.

  • 객체의 키는 PropertKey타입에 호환되는게 자연스럽기 때문에 해당 작업을 통해 훨씬 더 의도에 맞게 타입추론을 할 수 있습니다.
const obj = {
  a: { name: 'foo' },
  b: { name: 'bar' },
} as const;
const result = invert(obj, (value) => value);
// '{ readonly name: "foo"; } | { readonly name: "bar"; }' 형식은 'PropertyKey' 형식에 할당할 수 없습니다.
const obj = {
  a: { name: 'foo' },
  b: { name: 'bar' },
} as const;
const result = invert(obj, (value) => value.name);
// { foo: 'a', bar: 'b' }

Comment on lines +13 to +14
const invertedObj = {} as Record<TK, Exclude<K, symbol>>;
const keys = Object.keys(obj) as Exclude<K, symbol>[];
Copy link
Contributor Author

@ssi02014 ssi02014 Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.keys는 symbol을 제외합니다. 따라서 Exclude<K, symbol>[] 를 통해 symbol을 제외하였습니다.

또한, invertedObj 역시 symbol은 제외될 것이기 때문에 Record<TK, Exclude<K, symbol>> 로 정의합니다.

const object1 = {
  a: 'somestring',
  [Symbol(1)]: true,
};
Object.keys(object1); // ['a']

@ssi02014 ssi02014 merged commit d8e2e68 into main Jun 13, 2024
3 checks passed
@ssi02014 ssi02014 deleted the refac/invert branch June 13, 2024 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fix 버그 수정 및 코드 개선 @modern-kit/utils @modern-kit/utils
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant