Cached at:
09/16/26, 07:29 PM
# type declaration syntax - citrons.xyz
Source: [https://citrons.xyz/journal/2026-09-09](https://citrons.xyz/journal/2026-09-09)
most programming languages in common use today are influenced by C in one way or the other\. most do not use its syntax for types\. C’s type syntax can be quite confusing\.[it’s not*that*bad](https://citrons.xyz/why-c-type-syntax), but it’s definitely not worth imitating\. the biggest problem arises with user\-defined types, particularly with`typedef`\. without this feature, it is still possible to define structs and unions, but each usage must be prefixed with the keyword`struct`or`union`\. you cannot declare a variable`my\_struct a`; you must declare it`struct my\_struct a`\. but this ceases to be true with`typedef`, and as a result, the C grammar ceases to be context\-free\. in order to parse, for instance, the statement`foo \(\*x\);`, it is necessary to know whether`foo`is a type or not\. this is not ideal at all\.
some programming languages copy C’s declaration syntax \(examples: java, C\#, D\)\. this is not inherently confusing \(not more than C is already\), but it can get incredibly confusing because the type name often begins to be treated as if it were part of its own expression, which it is assuredly not in C\. one way or the other is fine, but it is extraordinarily ill\-advised to mix the two styles\. this is what truly leads to an inscrutable type syntax\. both of these are valid in java:
```
int myArray[];
int[] myArray;
```
C\+\+ is not real\.I have seen a few alternative syntaxes for type declarations across a variety of different languages\. all of these examples treat the type as its own self\-contained expression\.
## `identifier type`
this kind of syntax is employed by go, which is a favorite language of mine\. as go is sort of like a real sequel to C \(as used as an application language\), it can be seen as an iteration of the C idea\. first comes the identifier, and then the type\. it is somewhat like C, but backwards\. this is clever because the type is permitted to be an arbitrary compound expression, but the identifier is only a single token\.
a pointer type expression is prefixed with an`\*`\. an array is also expressed with a`\[\]`prefix, as opposed to a suffix\. that may be strange coming from C, but it means that there is no ambiguity as to what is an array of pointers as opposed to a pointer to an array\.
this works well in go, but if you’re designing a language, it’s worth noting that it could pose some parsing difficulties if you’re not careful to design the rest of the language in a particular way\. it is in essence two expressions juxtaposed\. despite the fact that one is an identifier and the other is a type expression, if a type expression appears where another kind of expression might, it would be ambiguous as to what kind of expression it is\. it must not be possible to juxtapose expressions in that manner in any other way\.
## `identifier : type`
this syntax is employed by ML\. it is also notably employed by rust, which is like if ML was C\+\+ \(not real\)\. this syntax is pretty respectable\. the type system of these languages, vastly unlike C, encompasses the scope of being an entire language in itself, like an embedded prolog\. there is a major focus on algebraic data types, and things as low level as pointers are not often used\. rust has references à la C\+\+, which are expressed as a prefix of`&`to the type\.
it seems popular at present to use the single colon for type annotations, with languages using it varying in the kinds of type systems they support\. off of the top of my head, I can think of zig, swift, and hare\. various languages that were once only dynamically typed have been extended with type annotations, and the colon may there be seen: typescript \(which has a very complex type system\), as well as python \(which now has type annotations that… do nothing?\!\)\.
it’s interesting that python uses the single colon for this purpose, since it also uses the colon for a completely unrelated load\-bearing syntactical construct\. that would be the main reason for not using this particular syntax, if you wanted to use the venerable and versatile colon for something else, especially if your language resembles hare, where the type declaration and the cast syntax are unified\. one may write`let a = b: u8;`\(which casts`b`to`u8`\) as they might write`let b: u8 = 128;`\. this definitely precludes using`:`for anything else within expressions for e\.g\. a C\-style ternary operator\.
it depends on language and style whether it is written as`identifier : type`or`identifier: type`\.
## `identifier :: type`
this is employed by haskell\. haskell is influenced by ML, but it does not use a single colon because it uses that for the cons operator\. strictly speaking, I believe that it*could*use a single colon for this purpose with no ambiguity, since every type declaration is a separate statement\. but perhaps using the token for both purposes would be confusing\.