흐름 오류 억제를보다 구체적으로 만들기
실수로 오류를 숨기지 않도록 흐름 오류 억제를 개선하고 있습니다.
내년에 Flow는 유형 시스템을 많이 변경하고 개선 할 계획 입니다. 그러나 이것의 결과 중 하나는 Flow가 기존 문제를 더 잘 찾을 수있게됨에 따라 코드에 더 많은 억제를 추가해야 할 수 있다는 것입니다.
Flow의 억제가 억제하려는 원래 오류 이상의 영향을 미치기 때문에 문제가 될 수 있습니다. 이것은 오류를 포착하는 Flow의 능력을 감소시킵니다. 이는 두 가지 속성의 결과입니다. 첫째, 흐름 억제는 유형 오류의 모든 부분에 위치 할 수 있고 두 번째는 흐름 억제가 모든 유형의 오류를 억제 할 수 있다는 것입니다 . 이러한 단점을 해결하려면 코드에서 오류가 실제로 발생하는 위치에 억제를 배치하고 억제하려는 오류의 종류를 지정하는 오류 코드를 포함해야합니다.
이 모든 것이 의미하는 바를 이해하기 위해 Flow의 유형 오류의 특성을 파헤쳐 보겠습니다.
유형 오류 란 무엇입니까?
Flow가 코드를 확인하는 동안 두 유형 간의 비 호환성 또는 잘못된 속성 액세스와 같은 문제가 발생하면 사용자에게 코드의 잘못된 점을 정확하게보고하는 오류를 생성합니다. 이러한 오류는 원인이 된 특정 상황에 따라 다양한 정보를 포함 할 수 있지만 가장 중요한 두 가지는 오류 의 종류 와 오류의 위치 입니다. 오류
의 종류 는 함수에 너무 많은 인수를 전달하는 것과 같은 단순한 것이 든 공용체 유형을 퍼뜨리는 것과 같은 복잡한 것이 든 상관없이 Flow가 코드에서 감지 한 나쁜 동작의 특정 특성을 인코딩합니다. 이 정보는 Flow에 정확히 어떤 종류의 정보를 사용자에게 표시할지 알려 주어 사용자가 어디에서 잘못되었는지 정확하게 설명합니다. 위치 오류는 오류가 코드에서의 위치에 대한 정보가 포함되어 있습니다. 오류에 포함될 수있는 위치 에는 기본 위치 (하나만있을 수 있음)와 보조 위치의 두 가지 종류가 있습니다.이 위치에는 많거나 전혀 없을 수 있습니다. 기본 위치는 대략 오류가 실제로 발생한 코드의 위치에 해당하는 반면 보조 위치는 오류와 관련된 유형 및 값의 정의 사이트에 대한 정보를 전달합니다. 예를 들면 :
function foo(x : number) : void {}
foo("hello");
/* error */
foo("hello");
^ Cannot call `foo` with `"hello"` bound to `x` because string [1] is incompatible with number [2].
References:
2: foo("hello");
^ [1]
1: function foo(x : number) : void {}
^ [2]
function foo(x : number) : void {}
let y : string = "hello";
foo(y);
/* error */
foo(y);
^ Cannot call `foo` with `y` bound to `x` because string [1] is incompatible with number [2].
References:
2: let y : string = "hello";
^ [1]
1: function foo(x : number) : void {}
^ [2]
그럼 억압이 뭐가 그렇게 잘못된 건가요?
음, 억제는 기본 및 보조 위치 모두에 적용될 수 있으므로 //$FlowFixMe
의 정의 위에 주석 foo
을 추가하면 위의 두 예에서 오류가 억제됩니다. foo
이를 사용하는 모든 오류에서 보조 위치로 나타나기 때문에 오류가 발생하는 모든 오류 foo
가 발생할 수있는 모든 곳에서이 하나의 억제에 의해 억제됩니다. foo
모든 유형의 인수 로 호출 할 수 있으며 Flow는 이에 대한 오류나 경고를 표시하지 않습니다. 이것은 Flow의 유형 검사에 대한 사용자의 신뢰를 떨어 뜨리고 그렇지 않으면 잡았을 버그를 프로덕션으로 만들 수있게합니다.
이 외에도 Flow의 억제는 억제가 포함하는 위치를 포함하는 한 모든 종류의 오류에 영향을줍니다. 즉, 단일 억제로 여러 종류의 여러 오류를 억제 할 수 있습니다. 이 위험을 확인하려면 다음 예를 고려하십시오.
// library file lib.js
function foo(x : number) : void {}
// impl file
const {foo} = require("lib.js");
let y : string = "hello";
// $FlowFixMe
foo(y);
이것에 대해 우리는 무엇을 할 것인가?
이 문제를 해결하기 위해 다음과 같이 변경합니다.
- 기본 위치를 적용합니다. 억제 동작을 변경하여 억제 기능이 기본 위치에있을 때 오류에만 적용되도록 할 것입니다. 예를 들어, 함수 정의에서 잘못된 호출을 억제하는 대신 이제 억제가 호출 사이트 자체에 있어야합니다. 이렇게하면 Flow는 함수에 대한 다른 잘못된 호출에 대해 경고 할 수 있습니다.
- 오류 코드를 추가하십시오. 또한 억제에 오류 코드를 추가하여 지정된 종류의 오류 만 억제합니다. 이렇게하면 발생하지 않을 것으로 예상했던 오류 유형이 예기치 않게 억제되는 것을 방지 할 수 있습니다.
- 억제 구문을 표준화합니다. 이전에는 오류 억제에 허용되는 구문을
.flowconfig
특정 프로젝트에 대해 에서 수동으로 구성 할 수 있었기 때문에 프로젝트 전체에서 일관되지 않은 억제 구문이 허용되었습니다. 위의 변경의 일부로 억제 구문을 표준화 할 것입니다.$FlowFixMe[incompatible-type]
또는$FlowExpectedError[incompatible-type]
형식 만 지원합니다 .
롤아웃
이 변경으로 인해 코드베이스에서 상당수의 오류가 무효화 될 수 있음을 알고 있습니다. 특히 라이브러리 코드에 억제 기능을 배치하는 습관이있는 경우 더욱 그렇습니다. 이러한 부담을 덜어주기 위해 다음과 같은 몇 가지 제안 사항이 있습니다.
- 새로 유효하지 않은 억제를 기본 위치로 재배치하려면 Flow 도구에 제공된
add-comments
및remove-comments
유틸리티 의 조합을 권장합니다 . 실행./tool remove-comments
하면 기본 위치에 있지 않기 때문에 더 이상 오류를 억제하지 않는 주석이 제거./tool add-comments
되고 억제되지 않은 위치에 새 억제가 적용됩니다. 이./tool
스크립트는 GitHub에서 Flow 저장소를 복제하여 액세스 할 수 있습니다. - 오류 코드가없는 억제는 해당 위치의 모든 오류를 계속 억제하지만 오류 코드 기능이 출시되면 위와 유사한 프로세스를 통해 코드베이스에 적절한 코드를 추가 할 수 있습니다. 이전 주석을 모두 제거하고 다시 추가
add-comments
하면 새로 추가 된 주석에 오류 코드가 포함됩니다.