클래스를 함수 in Type Script로 덮어쓰기

!
이것은 작가가 시험적으로 작성한 비망록이다.

제목.


이번에 처리한 것은 이하의 반이다.
export class Path {
  constructor(private pathString: string) {}

  toString() {
    return this.pathString;
  }

  fillIds(ids: { [id: string]: string | number }) {
    let _pathString = this.pathString;
      for (const id in ids) {
      _pathString = _pathString.replace(`:${id}`, ids[id].toString());
    }
    return new Path(_pathString);
  }

  appendQueries(queries: { [query: string]: string | number }) {
    const queryString = Object.keys(queries)
      .map((key) => `${key}=${queries[key]}`)
      .join("&");
    if (this.pathString.includes("?")) {
      return new Path(`${this.pathString}&${queryString}`);
    }
    return new Path(`${this.pathString}?${queryString}`);
  }
}
path 정보를 관리하는 클래스에서 '/resource/:resourceId' 형식의 path 문자열을 조작하고 출력할 수 있습니다.다음은 실행 예입니다.
const userVideoPagePath = new Path('/user/:userId/video/:videoId');

userVideoPagePath.toString(); // '/user/:userId/video/:videoId'

userVideoPagePath.fillIds({
  userId: 1000,
  videoId: 30,
}).toString(); // '/user/1000/video/30'

userVideoPagePath.fillIds({
  userId: 2000,
  videoId: 10,
}).appendQueries({
  timestamp: 1650753766,
}).toString(); // '/user/2000/video/10?timestamp=1650753766'
toString() 이외의 클래스 방법은 새로운Path 실례를 되돌려줍니다.이것은 method chaine가flument interface가 될 것을 의식한 것이다.

함수화


함수형 프로그래밍 기술을 사용하여 개작Path한 것이 바로 이것이다.
const pathGenerator = (pathString: string) =>
  ({
    generate: () => pathString,
    fillIds: (ids: { [idName: string]: string | number }) => {
      let _pathString = pathString;
      for (const idName in ids) {
        _pathString = _pathString.replace(`:${idName}`, ids[idName].toString());
      }
      return pathGenerator(_pathString);
    },
    appendQueries: (queries: { [queryName: string]: string | number }) => {
      const queryString = Object.keys(queries)
        .map((queryName) => `${queryName}=${queries[queryName]}`)
        .join("&");
      if (pathString.includes("?")) {
        return pathGenerator(`${pathString}&${queryString}`);
      }
      return pathGenerator(`${pathString}?${queryString}`);
    },
  } as const);
주어진 값pathString을 보류하고 함수별 지연 평가를 통해 새로운 값pathGenerator을 되돌려줍니다.항상 Generator라고 생각해서 이런 이름을 지었어요. 함수형 프로그램 설계에 더 적합한 이름이 있으면 알려주세요.🙇
실행 예는 다음과 같습니다.
const userVideoPagePathGenerator = pathGenerator('/user/:userId/video/:videoId');

userVideoPagePathGenerator.generate(); // '/user/:userId/video/:videoId'

userVideoPagePathGenerator.fillIds({
  userId: 1000,
  videoId: 30,
}).generate(); // '/user/1000/video/30'

userVideoPagePathGenerator.fillIds({
  userId: 2000,
  videoId: 10,
}).appendQueries({
  timestamp: 1650753766,
}).generate(); // '/user/2000/video/10?timestamp=1650753766'

다시 대입하지 않음으로 수정

fillIds()에서 for문을 사용했기 때문에 재대입이 필요합니다.let를 사용하는 것이 좋지 않기 때문에 for문을 사용하지 않는 문법으로 수정되었습니다.

정렬(Aray.map()


배열 함수를 사용하는 방법은 다음과 같습니다.
const pathGenerator = (pathString: string) => {
  generate: () => {/* 省略 */},
  fillIds: (ids: { [idName: string]: string | number }) => {
    const replacedPathString = pathString
      .split('/')
      .map(path => {
        if(path[0] === ':') {
          const idName = path.slice(1);
          return ids[idName];
        }
        return path;
      }).join('/');
    return pathGenerator(replacedPathString)
  },
  appendQueries: () => {/* 省略 */},
}

귀속


회귀를 이용한 작법은 다음과 같다.배열하는 방법을 사용하는 것보다 기술량이 많아 읽기 어려운 인상을 준다.
type PathGenerator = {
  generate: () => string;
  fillIds: (ids: { [idName: string]: string | number }) => PathGenerator;
  appendQueries: (queryies: {
    [queryName: string]: string | number;
  }) => PathGenerator;
};

const pathGenerator = (pathString: string): PathGenerator => {
  generate: () => {/* 省略 */},
  fillIds: (ids: { [idName: string]: string | number }) => {
    const [firstIdName] = Object.keys(ids);
    if (!firstIdName) { // 再帰の終了条件
      return pathGenerator(pathString);
    }
    const { [firstIdName]: firstValue, ...restIds } = ids;
    const replacedPathString = pathString.replace(`:${firstIdName}`, ids[firstIdName].toString());
    return pathGenerator(replacedPathString).fillIds(restIds); // 末尾再帰
  },
  appendQueries: () => {/* 省略 */},
}
fillIds()는 귀속 함수를 되돌려주기 때문에 type PathGenerator를 사용하지 않으면 유형 정의모드 추론을 할 수 없어서 오류가 발생했습니다를 한다.
유형 정의의 일부 기재량이 증가했지만 추론되는 유형은 읽기 어려워 회귀가 아니더라도 나름대로 유형 정의가 있을 수 있다고 생각한다.


함수형 프로그래밍과는 상관이 없지만 pathString이 / 로 시작되었는지 모듈로 표시하는 것이 편리할 것 같습니다.
const pathGenerator = (pathString: `/${string}`): PathGenerator => {
  // 他の箇所も適宜修正

최종 시스템


회귀의 방법으로 기재되어 있다.
type PathGenerator = {
  generate: () => `/${string}`;
  fillIds: (ids: { [id: string]: string | number }) => PathGenerator;
  appendQueries: (queryies: {
    [queryName: string]: string | number;
  }) => PathGenerator;
};

const pathGenerator = (pathString: `/${string}`): PathGenerator =>
  ({
    generate: () => pathString,
    fillIds: (ids: { [id: string]: string | number }) => {
      const [firstIdName] = Object.keys(ids);
      if (!firstIdName) {
        return pathGenerator(pathString);
      }
      const { [firstIdName]: firstValue, ...restIds } = ids;
      const replacedPathString = pathString.replace(
        `:${firstIdName}`,
        ids[firstIdName].toString()
      ) as `/${string}`;
      return pathGenerator(replacedPathString).fillIds(restIds);
    },
    appendQueries: (queries: { [queryName: string]: string | number }) => {
      const queryParams = Object.keys(queries)
        .map((key) => `${key}=${queries[key]}`)
        .join("&");
      if (pathString.includes("?")) {
        return pathGenerator(`${pathString}&${queryParams}`);
      }
      return pathGenerator(`${pathString}?${queryParams}`);
    },
  } as const);

총결산


제목이 정리된 것 같아서 다음에 하면 필요조건 정의부터 할 수 있어요.

좋은 웹페이지 즐겨찾기