interface BoundingBox {
lat: [number, number];
lng: [number, number];
}
import {Feature, Geometry} from 'geojson'; //geojson에서 명세를 받아온다.
declare let f: Feature;
function helper(coordinates: any[]) {}
const geometryHelper = (g: Geometry) => {
if (geometry.type === 'GeometryCollection') {
geometry.geometries.forEach(geometryHelper);
} else {
helper(geometry.coordinates); // OK
}
}
const {geometry} = f;
if (geometry) {
geometryHelper(geometry);
}
graphql를 사용할 때 apollo를 통해서 스키마를 얻을 수 있습니다.
query getLicense($owner:String!, $name:String!){
repository(owner:$owner, name:$name) {
description
licenseInfo{
spdxId
name
}
}
}
위를 바꾸면 밑의 예시처럼 나옵니다.
export interface getLicense_repository_licenseInfo {
__typename: "License";
/** Short identifier specified by <https://spdx.org/licenses> */
spdxId: string | null;
/** The license full name specified by <https://spdx.org/licenses> */
name: string;
}
export interface getLicense_repository {
__typename: "Repository";
/** The description of the repository. */
description: string | null;
/** The license associated with the repository */
licenseInfo: getLicense_repository_licenseInfo | null;
}
export interface getLicense {
/** Lookup a given repository by the owner and repository name. */
repository: getLicense_repository | null;
}
export interface getLicenseVariables {
owner: string;
name: string;
}
밑의 예시처럼 명확하게 표현해야 합니다.
interface Animal {
commonName: string;
genus: string;
species: string;
status: ConservationStatus;
climates: KoppenClimate[];
}
type ConservationStatus = 'EX' | 'EW' | 'CR' | 'EN' | 'VU' | 'NT' | 'LC';
type KoppenClimate = |
'Af' | 'Am' | 'As' | 'Aw' |
'BSh' | 'BSk' | 'BWh' | 'BWk' |
'Cfa' | 'Cfb' | 'Cfc' | 'Csa' | 'Csb' | 'Csc' | 'Cwa' | 'Cwb' | 'Cwc' |
'Dfa' | 'Dfb' | 'Dfc' | 'Dfd' |
'Dsa' | 'Dsb' | 'Dsc' | 'Dwa' | 'Dwb' | 'Dwc' | 'Dwd' |
'EF' | 'ET';
const snowLeopard: Animal = {
commonName: 'Snow Leopard',
genus: 'Panthera',
species: 'Uncia',
status: 'VU', // vulnerable
climates: ['ET', 'EF', 'Dfd'], // alpine or subalpine
};
타입스트립트는 구조적 타이핑(덕 타이핑)을 사용하기 때문에, 값을 세밀하게 구분하지 못하는 경우가 있습니다. 값을 구분하기 위해 공식 명칭이 필요하다면 상표(brand)를 붙이는 것을 고려해야 합니다.
상표(brand) 기법은 타입 시스템에서 동작하지만 런타임에 상표(brand)를 검사하는 것과 동일한 효과를 얻을 수 있습니다.
type SortedList<T> = T[] & {_brand: 'sorted'};
function isSorted<T>(xs: T[]): xs is SortedList<T> {
for (let i = 1; i < xs.length; i++) {
if (xs[i] > xs[i - 1]) {
return false;
}
}
return true;
}
function binarySearch<T>(xs: SortedList<T>, x: T): boolean {
// COMPRESS
return true;
// END
}
number type에서도 사용가능하지만 산술연산 후에 상표가 사라지기 때문에 실제로 사용하기에는 무리가 있습니다.
type Meters = number & {_brand: 'meters'};
type Seconds = number & {_brand: 'seconds'};
const meters = (m: number) => m as Meters;
const seconds = (s: number) => s as Seconds;
const oneKm = meters(1000); // Type is Meters
const oneMin = seconds(60); // Type is Seconds
const tenKm = oneKm * 10; // Type is number
const v = oneKm / oneMin; // Type is number
<이펙티브 타입스크립트> (댄 밴더캅 지음, 장원호 옮김, 인사이트, 2021)