In Dart, syntactically nice way to cast dynamic to given type or return null?

前端 未结 5 1718
囚心锁ツ
囚心锁ツ 2021-02-18 23:20

I have a dynamic x and I would like to assign x to T s if x is T, and otherwise assign null to s. S

相关标签:
5条回答
  • 2021-02-18 23:52

    Just use the as keyword

    final tweet = tweets[index] as Tweet;
    
    0 讨论(0)
  • 2021-02-19 00:03

    A combination of both prior two posts, without the logging.

    Fallback defaults to null when not provided.

    T cast<T>(dynamic x, {T fallback}) => x is T ? x : fallback;
    
    0 讨论(0)
  • 2021-02-19 00:08

    EDIT

    Figured out my answer had a huge problem, type check was incorrect. For example T is num returns false even if T is passed num. I temporarily fixed this issue for now by explicitly checking equality of T with the desired type like T == int && T == double but this might not work for checking subclassed types like T == num. Overall I edited my answer so it would work as is now. Although the answer is ongoing work and will be improved better when I find a solution for this type checking problem.


    Here's my modified version that supports parsing num (i.e. int, double) and DateTime within the tryCast:

    Usage

    var decimalNumber = tryCast<double>("42.42", fallback: 0);
    var integerNumber = tryCast<int>("42", fallback: 0);
    var currentTimestamp = tryCast<DateTime>(DateTime.now().toIso8601String(), fallback: DateTime.now());
    var someType = tryCast<SomeType>(jsonString['someType'], fallback: null);
    

    Solution

    /// Casts `x` of [dynamic] type to [T] type. With fallback value `fallback` if casting failed
    /// Supports tryParse from [String] to {[num],[DateTime], [Uri]}
    /// Edited from [this ](https://stackoverflow.com/a/59714798/10830091) StackOverflow answer
    T tryCast<T>(dynamic x, {T fallback}) {
    
      // tryParse from [String] `x`
      if (x is String) {
        if (T == int || T == double) {
          // tryParse to [num] (i.e. [int], [double])
          return num.tryParse(x) as T ?? fallback;
        } else if (T == DateTime) {
          // tryParse to [DateTime]
          return DateTime.tryParse(x) as T ?? fallback;
        } else if (T == Uri) {
          // tryParse to [Uri]
          return Uri.tryParse(x) as T ?? fallback;
        }
      }
    
      try {
        return (x as T) ?? fallback;
      } on CastError catch (e) {
        print('CastError when trying to cast $x to $T! Exception catched: $e');
        return fallback;
      }
    }
    

    Inspired from Magnus's answer.

    0 讨论(0)
  • 2021-02-19 00:09

    Dart 2 has generic functions which allows

    T cast<T>(x) => x is T ? x : null;
    
    dynamic x = something();
    String s = cast<String>(x);
    

    you can also use

    var /* or final */ s = cast<String>(x);
    

    and get String inferred for s

    0 讨论(0)
  • 2021-02-19 00:10

    I use the following utility function, which allows for an optional fallback value and error logging.

    T tryCast<T>(dynamic x, {T fallback}){
        try{
            return (x as T);
        }
        on CastError catch(e){
            print('CastError when trying to cast $x to $T!');
            return fallback;
        }
    }
    
    var x = something();
    String s = tryCast(x, fallback: 'nothing');
    
    0 讨论(0)
提交回复
热议问题