잘 보면 코드에 구현부가 없습니다. 함수 func나 class C에는 타입만 있고 구현부가 존재하지 않습니다. 변수에도 타입만 있고 값을 대입하지 않았습니다. 그래도 new C나 func(variable), NS.v처럼 값으로 사용할 수 있습니다. 외부 파일에 실제 값이 존재한다고 믿기 때문입니다. 그런데 외부 파일에 값이 없으면 코드를 실행할 때 에러가 발생하게 됩니다(런타임에러). 따라서 declare로 앰비언트 선언할 때는 반드시 해당 값이 실제로 존재함을 확인해야 합니다.
namespace와 enum은 왜 declare로 선언할까요? namespace를 declare로 선언하면 내부 멤버의 구현부를 생략할 수 있습니다. enum을 declare로 선언하면 자바스크립트로 변환할 때 실제 코드가 생성되지 않습니다. declare를 쓰는 경우에는 이미 다른 곳에 실제 값이 있다고 생각하기 때문입니다.
인터페이스와 타입 별칭도 declare로 선언할 수 있습니다.
declare interface Int {}
declare type T = number;
하지만 인터페이스와 타입 별칭은 declare로 선언하지 않아도 동일하게 작동하므로 굳이 declare를 붙일 필요가 없습니다.