对一个变量使用两种类型。打字稿

时间:2019-08-27 15:04:24

标签: typescript

转移的js打字稿,遇到了问题。以下函数适用于两种类型的数据,我看到此错误:

struct ContentView: View {
    @State private var width: CGFloat? = nil

    var body: some View {
        List {
            HStack {
                Text("1. ")
                    .frame(width: width, alignment: .leading)
                    .lineLimit(1)
                    .background(CenteringView())
                Text("John Smith")
            }
            HStack {
                Text("20. ")
                    .frame(width: width, alignment: .leading)
                    .lineLimit(1)
                    .background(CenteringView())
                Text("Jane Done")
            }
            HStack {
                Text("2000. ")
                    .frame(width: width, alignment: .leading)
                    .lineLimit(1)
                    .background(CenteringView())
                Text("Jax Dax")
            }
        }.onPreferenceChange(CenteringColumnPreferenceKey.self) { preferences in
            for p in preferences {
                let oldWidth = self.width ?? CGFloat.zero
                if p.width > oldWidth {
                    self.width = p.width
                }
            }
        }
    }
}

.onPreferenceChange

进行打字稿的第一步,请帮忙

3 个答案:

答案 0 :(得分:4)

出于以下几个原因,TypeScript无法将o1.createdDate || o1.dateTime.date视为有效:

  • 就运行时影响而言,最大的一项是假设o1.createdDate仅在undefined时才是falsy。但是空字符串也很虚假。如果有人打电话给这个:

    sortByDate({ createdDate: "" }, { createdDate: "" });
    

    然后您将最终致电stringToMillisecond(undefined),我怀疑这是一个错误。因此,我将放弃在这里对可能的string值使用虚假检查。

  • TypeScript编译器不允许您读取联合类型的属性值,除非联合的每个成员都包含带有该键的(可能是可选的)属性。因此,o1.createdDate是一个错误,除非您可以将differentiating之间的距离缩小为o1 first ,然后{em>缩小 OperationCreated价值观。一种实现方法是use the in operator,例如:

    "createdDate" in o1 ? o1.createdDate : o1.dateTime.date; // no error
    

    之所以可行,是因为编译器使用in检查在三元运算符的“ then”子句中将o1缩小为OperationCreated,或在“其他”子句。

所以我能想到的最简单的解决方法是:

OperationDefault

好的,希望能有所帮助。祝好运! Link to code

答案 1 :(得分:0)

此错误是因为编译器不知道o1o2Operation还是OperationCreated。您可以使用discriminated unions

我的解决方案(清洁)

interface DateTime {
  date: string;
}

interface OperationDefault {
  type: 'default';
  dateTime: DateTime;
}

interface OperationCreated {
  type: 'created';
  createdDate: string;
}

type Operation = OperationDefault | OperationCreated;

const sortByDate = (o1: Operation, o2: Operation) => {
  const d1 = o1.type === 'default' ? o1.dateTime.date : o1.createdDate;
  const d2 = o2.type === 'default' ? o2.dateTime.date : o2.createdDate;

  return stringToMillisecond(d1) - stringToMillisecond(d2);
};

答案 2 :(得分:0)

使用接口代替类型文字

 <tbody>
 <tr class="header">
     <td id="total_price">100</td> 
 </tr>
 <tr>
    <td>sub 1</td>
    <td><input type="text" name="min_price"></td>
    <button>save</button>
 </tr>
 <tr>
    <td>sub 2</td> 
    <td><input type="text" name="min_price"></td>
    <button>save</button>
 </tr>
 <tr>
    <td>sub 3</td>
    <td><input type="text" name="min_price"></td>
    <button>save</button>
 </tr>
 </tbody>

 $('#save').click(function(){
 ajax(data);
 var tr = $(this).prevUntil('tr.header');
 tr.find("td[id='total_price']").text(data.data.total_price);  
 });