타입은 프로그램을 실행하기 전에 “이 경계에는 어떤 값이 들어올 수 있는가?”를 검사하게 해 줍니다. 초기값만 봐도 타입이 분명한 지역 값에는 대개 타입을 적지 않아도 됩니다. 입력과 결과, 도메인의 중요한 선택을 드러내고 싶을 때 타입을 명시하세요.
하나의 프로그램에서 시작하기
다음 코드를 types.tpz로 저장합니다.
type Stage = "draft" | "ready"
function describe(stage: Stage, checks: int) -> string {
"{stage} after {checks} checks"
}
let checks = 3
let current: Stage = "ready"
let render: (Stage, int) -> string = describe
print(render(current, checks))먼저 타입 경계를 검사한 뒤 실행합니다.
topaz check types.tpz
topaz run types.tpz
결과는 다음과 같습니다.
ready after 3 checks결과에서 타입 읽어 내기
checks에는 타입 표기가 없습니다. 초기값이 정수이므로 토파즈가 int로 추론합니다. 반면 current에는 타입을 적었습니다. 이 프로그램이 임의의 string이 아니라 Stage만 받겠다는 의도를 나타냅니다.
Stage는 "draft" | "ready"라는 리터럴 유니온에 붙인 투명한 별칭입니다. 두 값 가운데 하나만 허용하고 다른 문자열은 거부합니다. 별칭은 선택에 이해하기 쉬운 이름을 붙이지만, 별도의 런타임 정체성을 만들지는 않습니다.
render에는 함수 타입이 쓰였습니다. (Stage, int) -> string은 “Stage와 int를 받아 string을 돌려주는 함수”라는 뜻입니다. 이름 있는 함수 describe가 바로 이 형태이므로 바인딩에 저장한 뒤 호출할 수 있습니다.
기본 타입 이름은 소문자로 씁니다. int, float, bool, string, 그리고 유닛 타입 ()가 있습니다. 자주 쓰는 컨테이너는 Array<T>, Map<K, V>, Set<T>처럼 이름 있는 생성자로 표현합니다. 예상 가능한 값의 부재에는 Option<T>, 복구 가능한 실패에는 Result<T, E>를 사용합니다.
의도에 맞는 형태 고르기
| 필요한 것 | 권장 형태 | 이유 |
|---|---|---|
| 타입이 분명한 지역 값 | 타입 추론 | 초기값만으로도 타입이 잘 드러납니다. |
| 공개 입력·결과 또는 중요한 지역 경계 | 타입 표기 | 검사기와 독자가 의도한 계약을 바로 알 수 있습니다. |
| 정해진 여러 대안 가운데 하나 | 유니온 또는 리터럴 유니온 별칭 | 허용되는 대안이 코드에 그대로 나타납니다. |
| 나중에 호출할 수 있는 값 | (int) -> bool 같은 함수 타입 | 매개변수와 결과 타입이 함수 값과 함께 유지됩니다. |
| 도메인 정체성, 필드, 이름 붙은 경우 | record, enum, newtype | 내부 모양이 비슷해도 서로 다른 타입으로 남습니다. |
type 별칭은 표현을 읽기 쉽게 만들지만 원래 타입과 구분되는 정체성은 만들지 않습니다. 모양이 비슷한 두 값을 섞는 것이 실제 오류라면 명목 데이터를 선택하세요. 레코드와 명목 데이터에서 record, enum, newtype의 생성과 패턴을 비교할 수 있습니다.
빈 값에는 문맥 제공하기
어떤 값은 그 자체만으로 타입을 모두 알려 주지 못합니다. 빈 배열에는 원소 타입이 없고, None만으로는 어떤 타입의 값이 없는지 알 수 없습니다. 타입 표기, 함수 매개변수, 선언된 결과 타입처럼 주변 문맥을 제공하세요.
let names: Array<string> = []
let selected: Option<int> = None여기서는 올바른 형태를 설명하기 위해 텍스트로 표시했습니다. 이 페이지에서 실제로 검증하는 프로그램은 위의 실행 예제입니다.
흔한 실수: 대상 언어의 타입 표기 가져오기
토파즈 컬렉션 타입은 Array<T>, Map<K, V>, Set<T>로 씁니다. 함수 타입은 매개변수 타입을 괄호로 묶고 -> 뒤에 결과 타입을 적습니다. 이 표기를 일정하게 사용해야 검사기와 생성 대상이 같은 소스 계약을 공유합니다.
정확한 한계
int와float사이에는 암묵적 변환이 없습니다.- 제네릭 타입 매개변수는 불변입니다. 내용이 비슷하다는 이유만으로 서로 다른 타입 인수가 호환되지는 않습니다.
- 제네릭 제약은 이름 있는 함수의 타입 매개변수에만 붙일 수 있습니다. 허용되는 1계층 형태는 함수와 제네릭에서 설명합니다.
- 재귀 타입 별칭, 분산(variance) 표기, 고위 다형성, 더 넓은 리플렉션은 아직 지원하지 않습니다.
- 문맥을 제공한 뒤에도 타입 매개변수가 결정되지 않는 빈 제네릭 값은 실행 중에 추측하지 않고 정적 오류로 거부합니다.
타입 추론, 타입 표기, 가변성이 아직 낯설다면 값과 함수를 다시 살펴보세요. 값의 부재와 실패를 구분하려면 Null·Option·Result·실행 오류로 이어가면 됩니다.