Closed
Description
Sometimes the type system is not expressive enough, and especially in Dart 2.x, knowing the explicit static type is important (and in many cases, required - for example, invoking methods, accessors, etc).
Prior art in other nominal type-system languages:
(This seems free in most structural ones)
Language | Support | Notes |
---|---|---|
Swift | No | It has as! , but that is similar to Dart's as |
Kotlin/Java | No | JVM has various unchecked modes, though. |
C# | No | |
C++ | Yes, with reinterpret_cast |
Current Support
There are three ways to "cast" that I know of:
Implicit Casts
void printSum(int a, int b) => print(a + b);
void foo(dynamic a, dynamic b) {
printSum(a, b);
}
or
void foo(dynamic a) {
TypeA actualA = a;
a.doThing();
}
Explicit Casts
void foo(dynamic a) {
var actualA = a as TypeA;
a.doThing();
}
Type Promotion
void foo(dynamic a) {
if (a is TypeA) {
a.doThing();
} else {
throw new UnsupportedError('Not expected: $a');
}
}
However, all of these fall short:
- Implicit casts hide sources of (real) bugs in code:
List<String> firstThree(List<String> names) {
return names.subList(0, 2);
}
void foo(List<String> allNames) {
// RUNTIME ERROR: Iterable<String> is not List<String>
var firstThree = firstThree(allNames.where((name) => name != 'Matan'));
}
... and is a warning with implicit-casts: false
turned on.
- Explicit casts, in both Dart2JS, DDC, and the Dart VM, have a cost:
Here is dart2js
:
void main(dynamic input) {
print((input as String).toUpperCase());
}
// Code shared by all dart2js compilations omitted.
main: [function(input) {
P.print(H.stringTypeCast(input).toUpperCase());
}, "call$1", "main__main$closure", 2, 0, 7]
- Type promotion forces awkward
if-else
handling code:
... as well as having a runtime cost for the is
check.
String getBestProprtyOf(dynamic a) {
if (a is Dog) {
return a.tail.description;
} else if (a is Cat) {
return a.paws.description;
} else {
// Uh... I have to fill this in.
throw new UnsupportedError('Neither a Cat or Dog');
}
}
Proposal
Add a as!
operator (or similar) - someone can think of a better syntax than me.
void foo(dynamic a) {
var actualA = a as! _TypeIKnowForSure;
print(actualA.propertyOnType);
}
Optionally, when assertions are enabled, I'd be OK for this use the normal as
.