typeset — Declare a variable or set its attributes (zsh canonical name) across all 5 shells
Equivalents in every shell
typeset -i count=0Bash accepts `typeset` as a SYNONYM for `declare` (POSIX-historical alias). Same flag set — `-i` integer, `-r` readonly, `-a` indexed array, `-A` associative, `-x` export, `-g` global-from-inside-function. New bash scripts conventionally use `declare`; `typeset` exists for ksh / zsh portability.
typeset -i count=0Canonical name in zsh (bash's `declare` works too but is non-idiomatic). Zsh-specific flags include `-T scalar=array sep` (tie scalar to array via separator), `-U` (unique elements in array), and `-A` (associative array — different access syntax from bash via `${(@kv)hash}`).
set -l count 0Fish has NO `typeset` or `declare`. `set` with scopes — `-l` (local), `-g` (global), `-U` (universal — persisted across sessions in `~/.config/fish/fish_variables`), `-x` (export) — covers all attribute combinations. Every variable is a LIST; no separate array primitive.
[int]$count = 0A type cast on the LHS gives a typed variable; subsequent assignments coerce or throw. `New-Variable -Name x -Value 1 -Option ReadOnly,AllScope` covers readonly + scope. Hashtables (`@{key=val}`) play the role of associative arrays.
set /a count=0`set /a` declares an integer (signed 32-bit) with arithmetic parsing of the RHS. Plain `set name=value` always creates a STRING. No arrays, no readonly, no associative variables — cmd's variable model is one flat string namespace.
Worked examples
Declare a typed integer variable
typeset -i count=0typeset -i count=0set -l count 0[int]$count = 0set /a count=0Declare a readonly variable
typeset -r MAX=100typeset -r MAX=100Set-Variable MAX 100 -Option ReadOnlyDeclare an associative array / hashmap
typeset -A user; user[name]=alicetypeset -A user; user[name]=alice$user = @{ name = 'alice' }Gotchas
- `typeset` and `declare` are the SAME builtin in bash. `typeset` came first historically (ksh, zsh) and bash adopted it as an alias — pick ONE per project for grep-ability. Zsh scripts conventionally use `typeset`; bash scripts conventionally use `declare`. See the existing /cmd/declare page for the shared semantics.
- Inside a function, `typeset X=v` makes `X` LOCAL to that function — even without `-l`. To declare a function-internal variable that is GLOBAL, use `typeset -g X=v`. Forgetting `-g` is a common cause of "why does this variable reset after the function returns?" bugs.
- Zsh's `typeset -U` (unique array) silently DEDUPLICATES on every assignment — `arr=(a b a c)` becomes `(a b c)`. Bash has no equivalent; porting a zsh `typeset -U PATH` to bash needs explicit dedup logic (`awk '!seen[$0]++'`) to keep the same behaviour.
- Bash `typeset -i x=5+3` evaluates the RHS as arithmetic — `$x` is `8`, not `5+3`. Subsequent assignments are ALSO arithmetic-parsed for the lifetime of `x`. Without `-i`, assignment is literal-string. The flag is sticky and reaches across function boundaries.
- POSIX `/bin/sh` (dash, ash, busybox sh) does NOT implement `typeset` OR `declare`. Scripts with `#!/bin/sh` headed for Alpine, OpenWrt, or Debian `dash` MUST use plain `x=value` and `readonly x` — these are the only POSIX-portable primitives. `shellcheck` flags this with code SC2039.