Reputation: 2598
Can anyone tell me what is T.Type
when I use JSONDecoder().decode()
?
I think it is type to decode data what I encoded.
So many example use above method like this:
JSONEncoder().decode([People].self, from: data)
If I check that method's definition I can see T.Type
.
I know the generics but what is T.Type
?
What's the difference between just T
and T.Type
?
when we declare some variables, we allocated their types like this
var someValue: Int
, not var someValue: Int.self
What is the T.Type
exactly and Type.self
?
Upvotes: 16
Views: 14385
Reputation: 13679
T.Type
is used in parameters and constraints to mean "the type of the thing itself, not an instance of the thing".
For example:
class Example {
static var staticVar: String { return "Foo" }
var instanceVar: String { return "Bar" }
}
func printVar(from example: Example) {
print(example.instanceVar) // "Bar"
print(example.staticVar) // Doesn't compile, _Instances_ of Example don't have the property "staticVar"
}
func printVar(from example: Example.Type) {
print(example.instanceVar) // Doesn't compile, the _Type_ Example doesn't have the property "instanceVar"
print(example.staticVar) // prints "Foo"
}
You get a reference to a Type's .Type
(the Type object itself) at runtime by calling TheType.self
. The syntax TheType.Type
is used in type declarations and type signatures only to indicate to the compiler the instance vs. type distinction. You can't actually get a reference to, for example, Int
's type at runtime or in your function implementations by calling Int.Type
. You would call Int.self
In the example code var someValue: Int
, the specific notation identifier: Type
(in this case, someValue: Int
) means that someValue will be an instance of Int. If you wanted someValue to be a reference to the actual type Int, you would write var someValue: Int.Type = Int.self
Remember that the .Type
notation is only used when declaring types and type signatures to the compiler, and the .self
property is used in actual code to retrieve a reference to the type object itself at execution time.
The reason why JSONDecoder().decode
requires a parameter of T.Type
(where T
conforms to Decodable
) is because any type conforming to Decodable
has an initializer init(from decoder: Decoder)
. The decode
method will need to call this init method on a type that conforms to Decodable
, not on an instance of a type that conforms to Decodable
. For example:
var someString: String = ""
someString.init(describing: 5) // Not possible, doesn't compile. Can't call an initializer on an _instance_ of String
var someStringType: String.Type = String.self
someStringType.init(describing: 5) // Iniitializes a String instance "5"
Upvotes: 42