Merge changes from topic "display-name-util"

* changes:
  Convert display-name-util.ts to TypeScript
  Rename files to preserve history
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index cbbddf8..aba094b 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -341,6 +341,7 @@
   }
 
   _getProjectConfig(project) {
+    if (!project) return;
     return this.$.restAPI.getProjectConfig(project).then(
         config => {
           this._projectConfig = config;
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js
deleted file mode 100644
index 2244cca..0000000
--- a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * @license
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import '../../../styles/shared-styles.js';
-import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
-import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
-import {PolymerElement} from '@polymer/polymer/polymer-element.js';
-import {htmlTemplate} from './gr-tooltip_html.js';
-
-/** @extends PolymerElement */
-class GrTooltip extends GestureEventListeners(
-    LegacyElementMixin(
-        PolymerElement)) {
-  static get template() { return htmlTemplate; }
-
-  static get is() { return 'gr-tooltip'; }
-
-  static get properties() {
-    return {
-      text: String,
-      maxWidth: {
-        type: String,
-        observer: '_updateWidth',
-      },
-      positionBelow: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-    };
-  }
-
-  _updateWidth(maxWidth) {
-    this.updateStyles({'--tooltip-max-width': maxWidth});
-  }
-}
-
-customElements.define(GrTooltip.is, GrTooltip);
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.ts b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.ts
new file mode 100644
index 0000000..c1a8eb2
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.ts
@@ -0,0 +1,55 @@
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import '../../../styles/shared-styles';
+import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
+import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
+import {PolymerElement} from '@polymer/polymer/polymer-element';
+import {htmlTemplate} from './gr-tooltip_html';
+import {customElement, property, observe} from '@polymer/decorators';
+
+export interface GrTooltip {
+  $: {};
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'gr-tooltip': GrTooltip;
+  }
+}
+
+@customElement('gr-tooltip')
+export class GrTooltip extends GestureEventListeners(
+  LegacyElementMixin(PolymerElement)
+) {
+  static get template() {
+    return htmlTemplate;
+  }
+
+  @property({type: String})
+  text = '';
+
+  @property({type: String})
+  maxWidth = '';
+
+  @property({type: Boolean, reflectToAttribute: true})
+  positionBelow = false;
+
+  @observe('maxWidth')
+  _updateWidth(maxWidth: string) {
+    this.updateStyles({'--tooltip-max-width': maxWidth});
+  }
+}
diff --git a/polygerrit-ui/app/utils/common-util.ts b/polygerrit-ui/app/utils/common-util.ts
index a7aca4c..fa53c66 100644
--- a/polygerrit-ui/app/utils/common-util.ts
+++ b/polygerrit-ui/app/utils/common-util.ts
@@ -25,9 +25,33 @@
 
 /**
  * Wrapper for the Object.prototype.hasOwnProperty method
+ *
+ * The type guard will also ensure if it returns true,
+ * the obj to check should have the property, see example below:
+ *
+ * @example
+ *
+ * interface A {
+ *   a: number;
+ * }
+ *
+ * interface B {
+ *   b: number;
+ * }
+ *
+ * function testFn(a: A | B) {
+ *   if (hasOwnProperty(a, "a")) {
+ *     // with the type guard, typescript now knows that a should be A type
+ *     // instead of A | B
+ *     a.a = 2;
+ *   }
+ * // without the type guard, it will throw error:
+ * // Property 'a' does not exist on type 'A | B'.
+ * }
  */
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export function hasOwnProperty(obj: any, prop: PropertyKey) {
-  // Typescript rules don't allow to use obj.hasOwnProperty directly
+export function hasOwnProperty<X extends {}, Y extends PropertyKey>(
+  obj: X,
+  prop: Y
+): obj is X & Record<Y, unknown> {
   return Object.prototype.hasOwnProperty.call(obj, prop);
 }