PowerShellで(値を初期化しない、型付けされた)変数は宣言できるか?

PowerShellでは型付けされた変数が宣言できます。


PS > [int]$i = 38
PS > $i = "chatmonchy"
Cannot convert value "chatmonchy" to type "System.Int32". Error: "入力文字列の形式が正しくありませ
ん。"
At line:1 char:3
+ $i <<<< = "chatmonchy"
$iはInt32に型付けされているので、Int32に変換できない文字列を代入すると、エラーになります。ただ、この方法だと、変数を初期化せねばなりません。

PS > [int]$j
0
これは一見上手くいっているようですが、単に、宣言されていない変数$jが$nullとして扱われ、それをInt32にキャストしたので0になっただけです。

PS > Get-ChildItem variable::i, variable::j

Name Value
---- -----
i 38
Get-ChildItem : Cannot find path 'j' because it does not exist.
At line:1 char:14
+ Get-ChildItem <<<< variable::i, variable::j
この通り、"j"という名前を持つ変数は存在しません。
初期化をせずに、変数の宣言を行う場合、むたぐちさんの記事の通り、New-Variableで行えます。しかし、このコマンドレットには、型を指定するパラメータは存在しないので、型付けされた変数は作成できません。
そもそも、New-Variableとは、PSVariable型のオブジェクトを作成するコマンドレットです。ここから先は、僕が想像で書いているのであまり信用できません。間違っていたらコメントなどいただけるとありがたいです……。New-Variableで作成された変数オブジェクトは、Variable ドライブに配置されます。ここにおかれた、PSVariable型とはどういうものかというと、

PS > Get-ChildItem Variable::i | Format-List


Name : i
Description :
Value : 38
Visibility : Public
Options : None
Attributes : {System.Management.Automation.ArgumentTypeConverterAttribute}
このような感じです。つまり、$iというのは、(Get-ChildItem Variable::i).Valueの省略記法です。実際、(Get-ChildItem Variable::i).Value に値を代入すると、$iの値が変化します。
ここで、型付けされた変数に話を戻します。型付けされた変数は、そうでない変数とどこかが違うはずです。見たら速攻で気付くと思いますが、普通の変数のAttributesは$nullなのに、$iはそうではありません。$iは、intに型付けされているので、Attributesが$nullじゃないのです。
PSVariable.AttributesはPSVariableAttributeCollectionというコレクションで、$iの場合、中にはArgumentTypeConverterAttributeというクラスのオブジェクトが入っています。こいつが、型付けされた変数が型付けされている所以です。
整理すると、New-VariableでPSVarivableオブジェクトを作成した後、Attributesコレクションに、ArgumentTypeConverterAttributeをAddしてあげれば、型付けされた変数になるはずです。しかし、残念ながらArgumentTypeConverterAttributeに関するドキュメントは検索しても全く存在しておらず、コンストラクタもみつからないので、ここでお手上げでした……。一応、

PS > [int]$i = 0
PS > (New-Variable -Name j -PassThru).Attributes.Add((Get-ChildItem Variable:i).Attributes[0])
PS > $j -eq $null
False
PS > $j = "bustour"
Cannot convert value "bustour" to type "System.Int32". Error: "入力文字列の形式が正しくありません。
"
At line:1 char:3
+ $j <<<< = "bustour"
で、$jを初期化せずに、型付けされた変数にすることが出来た!!! とは言えるけど……。ちなみに、$jは属性を指定しなければ値$nullなのですが、Attributesを設定した瞬間に値が0になります。不思議。