🚨codeChallenge에서 요구한건 여러개의 callsigniture만들기였다.
하지만 지문을 잘못이해하고 여러개 이부분에 꽂혀서 한번에 만들어주지~! 하면서 미래를 보지 못한채 class로 만들어버리는 이슈 발생
class Default<T>{
//전달받을 프로퍼티 item T[]선언
//class의 프로퍼티를 사용할일이 없다면 지워도됨(이 코드에선 지워도됨)
protected item:T[]
//constructor또한 사용 안하면 지워도됨
constructor(){
//[] 초기화 시켜주기
this.item = []
}
//배열의 마지막 값을 받을 함수
last(item:T[]):T{
return item[item.length - 1]
}
//두번째 인자를 배열의 첫번째에 넣는 함수
prepend(item:T[],item2:T):T[]{
return [item2,...item]
}
//배열을 합쳐서 새로운 배열을 리턴하는 함수
mix(item:T[],item2:T[]):T[]{
return [...item,...item2]
}
//배열의 길이
count(item:T[]):number{
return item.length
}
//배열에서 두번째 인자의(item2) index값 리턴 값이 없다면 null리턴
findIndex(item:T[],item2:T):number | null{
return item.indexOf(item2) !== -1 ? item.indexOf(item2) : null
}
//배열 자르기 item3은 옵션
slice(item:T[],item2:number,item3?:number):T[]{
return item.slice(item2,item3)
}
}
const arr = new Default<number | string>()
const lastItem = arr.last([1, 2, 3, 4, "bye"])
const prependItem = arr.prepend([1,2,3,4,5],"hola")
const mixItem = arr.mix([1,2],["hi"])
const countItem = arr.count([1,2,3,4,5,6,7])
const findIndexItem = arr.findIndex([1,2,3,4,5,6],3)
const sliceItem = arr.slice([1,2,3,4,5,6,7],3)
class로 만들면서 class Default<T>여기서 <T>라고 제네릭을 선언해줬는데 왜 아래에서 인스턴스를 새성할때 new Default<number | string>()이렇게 써줘야하는지 이해가 안갔다.
코드를 하면서 문서도 찾아보면서 알아낸 바로는 인스턴스를 생성할때 구체적인 타입을 명시함으로서 타입의 안정성이 높아진다.
그리고 클래스에 바로 쓰지 않고 인스턴스에서 쓰면 클래스의 재사용성이 높아진다.
정의//callsigniture를 만들기 위해 type 지정해 Initial<T> generic을 넣어준다.
type Initial<T> = {
//여기 안에서 함수의 타입들을 지정해준다.
//class를 사용해서 만들었을때 함수 괄호 안에 넣어줬던것들
last:(item:T[]) => T
prepend:(item:T[],item2:T) => T[]
mix:(item:T[],item2:T[]) => T[]
count:(item:T[]) => number
findIndex:(item:T[],item2: T) => number | null
slice:(item:T[],item2:number,item3?:number) => T[]
}
//기능을 구현하기 위해 객체 변수 생성
const Default: Initial<number | string> = {
//기능 구현 이름은 Initial안에 들어 있는 메소드 이름과 동일해야함
last:(item) => item[item.length - 1],
prepend:(item,item2) => [item2,...item],
mix:(item,item2) => [...item,...item2],
count:(item) => item.length,
findIndex:(item,item2) => item.indexOf(item2) !== -1 ? item.indexOf(item2) : null,
slice:(item,item2,item3) => item.slice(item2,item3),
}
//메소드 호출을 위해 Default 참조
const lastItem = Default.last([1,2,3,4,"bye"])
const prependItem = Default.prepend([1,2,3,4,5],"hola")
const mixItem = Default.mix([1,2],["hi"])
const countItem = Default.count([1,2,3,4,5,6,7])
const findIndexItem = Default.findIndex([1,2,3,4,5,6],3)
const sliceItem = Default.slice([1,2,3,4,5,6,7],3)
class로 만들었던것들을 callsigniture로 쓰기위해 type을 만들어 함수의 타입을 각각 지정해주고 기능을 구현하기 위해 Default라는 객체를 만들어 각각의 기능을 넣어주고 마지막에 Default을 참조해 메소드를 호출시켰다.
class로 만든걸볼때 type으로 callsigniture를 만드는것보다 쉽다고 생각했다.
class 내부에 함수를 만들어 한번에 타입지정과, 구현할 코드를 만들 수 있기때문이다.
그래도 callsigniture를 쓰면 가독성이 좋고 코드가 간결해 보인다.
이래저래 의도치 않게 두번의 코드를 작성했는데 쓰는 코드는 동일한데 어떻게 배치하느냐의 차이같다.
//class
last(item:T[]):T{
return item[item.length - 1]
}
//callsigniture
type Initial<T> = {
last:(item:T[]) => T
}
const Default: Initial<number | string> = {
last:(item) => item[item.length - 1],
}