@Override
    public <X> TypeInformation<X> getTypeAt(String fieldExpression) {
        Matcher matcher = PATTERN_NESTED_FIELDS.matcher(fieldExpression);
        if (!matcher.matches()) {
            if (fieldExpression.equals(ExpressionKeys.SELECT_ALL_CHAR)
                    || fieldExpression.equals(ExpressionKeys.SELECT_ALL_CHAR_SCALA)) {
                throw new InvalidFieldReferenceException(
                        "Wildcard expressions are not allowed here.");
            } else {
                throw new InvalidFieldReferenceException(
                        "Invalid format of Row field expression \"" + fieldExpression + "\".");
            }
        }

        String field = matcher.group(1);

        Matcher intFieldMatcher = PATTERN_INT_FIELD.matcher(field);
        int fieldIndex;
        if (intFieldMatcher.matches()) {
            // field expression is an integer
            fieldIndex = Integer.valueOf(field);
        } else {
            fieldIndex = this.getFieldIndex(field);
        }
        // fetch the field type will throw exception if the index is illegal
        TypeInformation<X> fieldType = this.getTypeAt(fieldIndex);

        String tail = matcher.group(3);
        if (tail == null) {
            // found the type
            return fieldType;
        } else {
            if (fieldType instanceof CompositeType) {
                return ((CompositeType<?>) fieldType).getTypeAt(tail);
            } else {
                throw new InvalidFieldReferenceException(
                        "Nested field expression \""
                                + tail
                                + "\" not possible on atomic type "
                                + fieldType
                                + ".");
            }
        }
    }
@Test
    void testGetTypeAt() {
        RowTypeInfo typeInfo = new RowTypeInfo(typeList);

        assertThat(typeInfo.getFieldNames()).isEqualTo(new String[] {"f0", "f1", "f2"});

        assertThat(typeInfo.getTypeAt("f2")).isEqualTo(BasicTypeInfo.STRING_TYPE_INFO);
        assertThat(typeInfo.getTypeAt("f1.f0")).isEqualTo(BasicTypeInfo.SHORT_TYPE_INFO);
        assertThat(typeInfo.getTypeAt("f1.1")).isEqualTo(BasicTypeInfo.BIG_DEC_TYPE_INFO);
    }