언어 기초

타입

함수의 입력·반환 타입을 고르고, 허용할 값에 이름을 붙이며, 빈 컬렉션의 타입을 지정합니다.

함수가 받을 값과 반환할 값의 타입을 고르고 선언에 적어 보세요. 예제에서 타입 추론, 유니온, 함수 타입을 읽는 방법을 익힙니다.

첫 프로그램을 따라 토파즈를 설치하세요. 함수와 지역 값을 처음 다룬다면 값과 함수부터 시작하세요.

타입을 지정한 함수 검사하고 실행하기

작업 폴더에 다음 코드를 types.tpz로 저장하세요.

TOPAZ
type 단계 = "draft" | "ready"

function 설명(단계값: 단계, 검사수: int) -> string {
    "{단계값} after {검사수} checks"
}

let 검사수 = 3
let 현재: 단계 = "ready"
let 표시함수: (단계, int) -> string = 설명

print(표시함수(현재, 검사수))

같은 폴더에서 파일을 검사하고 실행하세요.

BASH
topaz check types.tpz
topaz run types.tpz

검사가 성공하면 종료 코드는 0입니다. 프로그램은 다음 줄을 출력합니다.

출력
ready after 3 checks

입력 타입과 반환 타입 읽기

설명은 단계와 int를 받아 string을 반환합니다. 함수 타입 (단계, int) -> string도 같은 입력과 반환값을 나타냅니다. 이 타입으로 선언한 표시함수에 함수를 담아 나중에 호출할 수 있습니다.

토파즈는 검사수의 초기값 3을 보고 타입을 int로 정합니다. 이를 타입 추론이라고 합니다. 현재: 단계처럼 타입을 직접 적는 것을 타입 표기라고 합니다.

단계는 유니온 "draft" | "ready"에 붙인 이름입니다. 유니온은 나열한 선택지 가운데 하나를 받습니다. 여기서는 두 문자열 리터럴이 선택지이므로 "waiting" 같은 다른 문자열은 타입 검사에서 거부합니다. 이 오류가 나면 types.tpz에서 현재에 대입한 값을 "draft"나 "ready"로 고치세요.

type 별칭은 기존 타입에 다른 이름을 붙입니다. 단계와 "draft" | "ready"는 같은 타입입니다. 별칭이 값을 새로 감싸지는 않습니다.

용도에 맞는 타입 고르기

필요한 것사용할 형태
초기값으로 타입을 알 수 있는 지역 값let 검사수 = 3 같은 타입 추론
함수의 입력·반환 타입 명시타입 표기
여러 타입이나 리터럴 값 중 하나유니온
값으로 저장하거나 전달할 함수(int) -> bool 같은 함수 타입
필드나 저장한 값이 같아도 구별할 타입명목 타입인 record, enum, newtype

명목 타입은 선언에 따라 구별합니다. 예를 들어 필드가 같아도 따로 선언한 두 레코드 타입은 서로 다릅니다. 생성과 패턴은 레코드와 명목 데이터에서 확인하세요.

기본 타입은 소문자로 int, float, bool, string이라고 씁니다. 유닛 타입은 ()로 쓰며 값도 ()입니다. unit이라는 타입 별칭은 없습니다.

컬렉션에는 Array<T>, Map<K, V>, Set<T>를 쓰며 각 문자는 타입을 나타냅니다. 예를 들어 Array<string>은 문자열을 담습니다. 값이 없을 수 있으면 Option<T>, 성공이나 복구 가능한 오류를 반환하려면 Result<T, E>를 사용하세요.

빈 값에 타입 지정하기

빈 배열에는 타입을 추론할 원소가 없습니다. None도 값이 있을 때의 타입을 알아야 합니다. 다음 선언은 그 타입을 직접 적습니다.

let 이름들: Array<string> = []
let 선택값: Option<int> = None

첫 선언은 빈 문자열 배열을 만듭니다. 둘째는 값이 없는 Option<int>를 만듭니다. 함수 매개변수, 반환 타입, 주변 표현식에서도 필요한 타입을 알 수 있습니다. 그래도 타입을 정하지 못하면 검사기가 거부합니다.

타입 인수의 개수와 타입 맞추기

타입 이름을 쓸 때는 선언에 맞는 개수의 타입 인수를 적으세요. Array<string>에는 하나, Map<string, int>에는 둘이 필요합니다. 기본 타입과 타입 매개변수에는 타입 인수를 붙이지 않습니다. 타입 별칭과 사용자 선언에도 같은 규칙을 적용합니다.

제네릭 타입은 무공변입니다. 타입 인수의 범위를 넓혀도 두 컬렉션 타입을 서로 바꿔 쓸 수 없다는 뜻입니다. 예를 들어 Array<int>는 Array<int | string>이 아닙니다.

표준 라이브러리 타입 template, JSONValue, File, Bytes, ByteBuffer, Path, Regex, Match, TOMLValue, URL, Date, BigInt, Decimal, RoundingMode에는 타입 인수를 붙이지 않습니다. File은 open이 반환하는 리소스 타입입니다. 내부 표현에 접근하지 않고 제공하는 연산으로 사용합니다.

그 밖의 타입 규칙

  • int와 float는 서로 암묵적으로 변환되지 않습니다.
  • 프로토콜 제약 조건은 이름 있는 함수의 타입 매개변수에 선언하세요. 함수 본문에서 사용할 연산을 어떻게 정하는지는 함수와 제네릭에서 설명합니다.
  • 재귀 타입 별칭, 분산 표기, 고위 다형성, 일반적인 리플렉션은 지원하지 않습니다.

이 타입으로 재사용할 함수를 만들려면 함수와 제네릭으로 이어가세요. 값이 없는 경우와 오류의 표현은 Null·Option·결과·fault에서 고를 수 있습니다.