TypeScript는 Vue입니다.set 금형을 안전하게 하려면

16619 단어 TypeScriptVue.js

입문


어렵게 TypeScript를 사용했기 때문에 Vue.set 안전도 원합니다!누구나 한 번쯤은 생각해 봤겠죠?
이 글에서 우리는 과정에서 Vue.set 금형을 안전하게 실현하는 것을 소개할 것이다.

TL;DR


최종 코드
Vue.typedSet = (object: any, key: any, value: any) => Vue.set(object, key, value);
// src/@types/vue.d.ts
import Vue from 'vue';

declare module 'vue/types/vue' {
  interface VueConstructor {
    typedSet<T extends object, K extends keyof T>(object: T, key: K, value: T[K]): T[K];
  }
}

Vue.세트 유형

Vue.set의 유형은 vue/types/vue.d.ts 에서 다음과 같이 정의됩니다.
  set<T>(object: object, key: string | number, value: T): T;
  set<T>(array: T[], key: number, value: T): T;
수조에 대해서는 문제가 없지만 대상의 값은 원래의 유형과 다른 값을 설정할 수 있다.
이것은 좋지 않기 때문에 금형을 안전하게 하는 방법을 생각해 보세요.

형 보안 Vue.set 형식 고려


우선 금형 안전Vue.set이 어떤지 생각해 봅시다.
두 번째 매개변수는 첫 번째 매개변수에서 가져올 수 있는 키워드를 지정하고, 세 번째 매개변수는 두 번째 매개변수에서 지정한 첫 번째 매개변수의 키워드 값과 동일한 유형을 지정할 수 있습니다.
유형 정의에 쓰면 다음과 같습니다.
  set<T extends object, K extends keyof T>(object: T, key: K, value: T[K]): T[K];
이제 그룹과 대상이 모두 가능한 설정 방법 형식을 정의할 수 있습니다.

VueConstructor의 유형 지정

Vue.set 유형 vue/types/vue.d.tsVueConstructor 을 확장적으로 정의합니다.
TypeScript는 객체 범위 전체@types 이하의 유형 정의 파일을 컴파일에 자동으로 포함합니다.
이번에는 src/@types/ 아래에 vue.d.ts라는 형식 정의 파일을 만들었습니다.
이 안에서 확장VueConstructor의 유형 정의를 써 보세요.
// src/@types/vue.d.ts
import Vue from 'vue';

declare module 'vue/types/vue' {
  interface VueConstructor {
    set<T extends object, K extends keyof T>(object: T, key: K, value: T[K]): T[K];
  }
}
declare module 후속 모듈 이름(이번 상황에서 지정한 node_modules/vue 이하types/vue.d.ts의 내부를 확장할 수 있습니다.declare module 'vue/types/vue' { ... }{ ... } 인터페이스를 덮어쓸 수 있습니다.

써봤어요.


이제 유형 보안으로 vue/types/vue.d.ts 확장할 수 있습니다.한번 해볼게요.

포인트는 이제 보완할 수 있어요!다음은 부정확한 값을 설정해 봅시다!

아이고, 아이고... export 문자열인데 Vue.set 로 설정했네.이건 안돼.

잘못된 유형을 설정할 수 있는 이유


TypeScript의 인터페이스 확장은 기존 정의를 위반하지 않는 형태로만 확장할 수 있습니다.
또한 함수에 대해 매개 변수 수가 동일하게 정의된 함수가 있으면 검사합니다.
즉, 이 현상은 유형이 안전한 사람의 유형 검사에 걸렸지만 후속 유형이 안전하지 않은 사람의 유형 검사가 통과했기 때문에 OK라는 것이다.
따라서 순수하게 확장obj.foo만 한다면 원래의 정의가 뒤에 있기 때문에 아무런 의미가 없다.

다음 유형 정의 참조 피하기


TypeScript에서 다음 유형 정의를 찾는 기준은 완전히 동일한 유형에 국한됩니다.
다음 유형 정의0의 경우 매개변수만 있으면 유형 오류가 발생하지 않습니다.
interface Sample {
  fn(foo: string) => void;
  fn(bar: any) => void;
}

fn('a');
fn({});
두 번째 매개 변수가 있는 방법을 추가하려고 하면 정확한 형식 검사가 진행됩니다.당연하지.
interface Sample {
  fn(baz: string, qux: number) => void;
  fn(foo: string) => void;
  fn(bar: any) => void;
}

fn('a', 0); // OK
fn(0, 0);   // Error
즉, 매개 변수의 수를 늘리면 후속 형식 정의를 인용하지 않는다는 것이다.
이를 악용하여 유형 정의에만 로고를 추가합니다.
// src/@types/vue.d.ts
import Vue from 'vue';

declare module 'vue/types/vue' {
  interface VueConstructor {
    set<T extends object, K extends keyof T>(object: T, key: K, value: T[K], isTyped: true): T[K];
  }
}
현재 Vue.set 를 네 번째 매개 변수에 전달하면 금형 안전fn()을 사용할 수 있습니다.

아까 예에서 문자열 이외에는 설정할 수 없습니다.
그렇다면 끝내고 싶지만 언젠가 true의 네 번째 파라미터에 로고를 추가할 때 이 유형의 정의는 곤란하다.
또 거짓 유형 정의 자체가 흑마술이기 때문에 가슴을 펴고 사용하지 못한다.
우리 대안을 생각해 봅시다.

Vue.설치 세트

Vue.set의 확장이 심각한 것 같다.
그럼 차라리 새로운 전역 방법 Vue.typedSet 을 정의합시다.
Vue를 추가하는 전역적인 방법은 간단합니다. 예를 들어 Vue.set 속성만 생성하면 됩니다.Vue.typedSetVue.newGlobalMethod = Function의 별명일 수 있으므로 실현 자체는 다음과 같다.
Vue.typedSet = (object: any, key: any, value: any) => Vue.set(object, key, value);
Nuxt를 사용하면 플러그인을 정의하고 서버 클라이언트에서 호출하는 데 문제가 없습니다.
// @/plugins/vue-typedSet.ts`
import { Plugin } from '@nuxt/types';

const plugin: Plugin = (context, inject) => {
  Vue.typedSet = (object: any, key: any, value: any) => Vue.set(object, key, value);
});

export default plugin;
마지막으로 방금 확장된 형식에 정의된 방법의 이름을 Vue.typedSet 로 변경합니다.
// src/@types/vue.d.ts
import Vue from 'vue';

declare module 'vue/types/vue' {
  interface VueConstructor {
    typedSet<T extends object, K extends keyof T>(object: T, key: K, value: T[K]): T[K];
  }
}
새로운 방법을 정의했지만, 이렇게 하면 금형 안전Vue.set이 가능합니다!

기쁘고 축하할 만하다.

참고 자료

  • Vue 확장 - vue.js
  • foo,bar,baz의 후속 - Qiita
  • 좋은 웹페이지 즐겨찾기